问题
Fragments
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflater provided
View view;
...
return view;
}
BaseAdapter:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//have to make a constructor to get an inflater
....
return view;
}
Why does BaseAdapter
's getView()
method parameters doesnt provide an LayoutInflater
unlike Fragment
's onCreateView()
? Wherein in this method we are expected to inflate views?
Inflating views requires that we have a reference to an LayoutInflater
.
回答1:
The "why a getView method doesn't use the context as a parameter" resides in its using. There are many diffences between Activity
, Fragment
and Adapter
, just to remember:
- an Activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI.
- a Fragment is a piece of an application's user interface or behavior that can be placed in an Activity.
- an Adapter object acts as a bridge between an AdapterView and the underlying data for that view. It is also responsible for making a View for each item in the data set.
There is a big difference in its using and to be more specific:
- An Activity implements onCreate and calls
setContentView(int)
to inflate the activity's UI. - The Fragment uses onCreateView method to instantiate its user interface view.
- While the Adapter uses getView to get a View that displays the data at the specified position, either create a View manually or inflate it from an XML layout file.
The mainly difference is that Activity and Fragment return an user interface view whereas an Adapter returns the view which takes place inside the user interface. The user don't interact with the Adapter.
getView()
method does not provide a LayoutInflater
(or a Context
) as a parameter because this method returns a View corresponding to the data at the specified position and not an UI. Then, this method needs a parent view
instead of a context
because it returns many views (in a loop) and not only one interface.
I am not sure about it, however I think, as Manish Mulimani said, this is also a save resources ways, because if you do a loop to create many views and attach each time the entire context, you will use some useless resources just to display the simple views in your UI.
回答2:
One of the reason could be, most of the times Views will be reused. When the view is reused i.e. the second parameter View is not null, you will not be using the Inflater. Hence that could be the reason why the API has been designed in that way.
In case of Fragments, you will have to create a layout either by using APIs or inflating a resource. Since the best practice is to separate out the UI design from Activity's behavior, most of the time Inflater is used. These are the statements provided in the official documentation.
To return a layout from onCreateView(), you can inflate it from a layout resource defined in XML. To help you do so, onCreateView() provides a LayoutInflater object.
回答3:
I don't see what the problem is...
public class MyAdapter extends BaseAdapter {
private LayoutInflater inflater;
public MyAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
...
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(...);
}
...
}
回答4:
In the constructor you get yhe context and the data you want the adapter to use. also , you need to take care of getItem() and getCount() methods.
the getView() method calls everytime the View that uses the adapter needs to Draw itself. you should check if the convert view is null , if it is null you should inflate your layout there an if not you need to make the rootview from the convert View. (the convert view is the cashing mechanisem that helps the adapter to be more eficient , the adapter recycles View objects instead of creating new views Object , if you don't add this check your Gallery will not run smoothly)
here is an example of a base adapter that display names of leagues that it recived as an Array:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.LinearLayout;
import android.widget.TextView;
public class GalleryAdapter extends BaseAdapter {
Context context;
private String[] leaguesName;
public GalleryAdapter(Context context,String[] leaguesName )
{
this.context=context;
this.leaguesName=leaguesName;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return leaguesName.length;
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return leaguesName[arg0];
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View root;
counter++;
if(convertView==null)
{
LayoutInflater lif = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
root=lif.inflate(R.layout.gallery_text_view, null);
}
else
root=convertView;
TextView tv =(TextView) root.findViewById(R.id.league_name_tv);
tv.setText(leaguesName[position]);
return root;
}
}
回答5:
You do not necessarily need LayoutInflater you can do:
View.inflate(context, resource, parent)
As to the Context
subclasses of BaseAdapter
do provide getContext()
. I do not know why BaseAdapter does not have a Context parameter in the constructor, probably, to make BaseAdapter
as abstract as possible.
Indeed, BaseAdapter
abstraction uses only View
and ViewGroup
and DataSetObserver
abstractions. Context
would be an implementation detail and so BaseAdapter
does not use it.
来源:https://stackoverflow.com/questions/23051466/android-baseadapter-context