0

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.

Rick Royd Aban
  • 904
  • 6
  • 33
  • Yes you require a context for LayoutInfalter. You can pass the context to the constructor of Adapter class. Inflate views in getView. check this http://stackoverflow.com/questions/11945563/how-listviews-recycling-mechanism-works – Raghunandan Apr 14 '14 at 03:30
  • yes I am aware of that. We have to spend some time creating for our constructors and allocating space for our context instance though – Rick Royd Aban Apr 14 '14 at 03:33
  • You can initialize the inflater once in the constructor and then inflate views when convertView is null. You can also use viewholder. – Raghunandan Apr 14 '14 at 03:38
  • The answer might be *"because"*... because Google built it in this way. – Blo Apr 14 '14 at 04:54
  • there might be some reason for this – Rick Royd Aban Apr 14 '14 at 04:57

5 Answers5

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.

Manish Mulimani
  • 17,535
  • 2
  • 41
  • 60
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.

Blo
  • 11,903
  • 5
  • 45
  • 99
  • thank you for providing a well defined answer. I appreciate it. However, I think that you can interact with the adapter views. For example, you can delete an item on your adapter by clicking a delete button on one of the adapter's view elements. – Rick Royd Aban Apr 14 '14 at 06:21
  • Yes @RickRoydAban, you're right but I meant you're not **directly** interact with an adapter. You can interact with the UI, and the UI provides a refresh of the adapter. Maybe I'm wrong, however I think this is the second reason to why you don't have a context parameter. The Activity and Fragment "host" the adapter and the contrary is difficult. – Blo Apr 14 '14 at 06:28
  • about "The Activity and Fragment "host" the adapter and the contrary is difficult" can you please expand? – Rick Royd Aban Apr 14 '14 at 08:23
  • 1
    This is not quite well, my verb, I confess. But it's to say: *"An user interface (Activity, Fragment) have a method to display views (an Adapter) whereas an adapter cannot provide an user interface."* - In other words, an UI can have an Adapter into it, inside its class. An Adapter can't provide an UI inside its methods, this last uses it and not create or provide it. @RickRoydAban – Blo Apr 14 '14 at 17:22
  • 1
    Good point there @Fllo. As to what I understood, user interfaces **create** UIs (`onCreate()` for Activities and `onCreateView()` for Fragments) while Adapter only **provides** a UI (`getView()`) From that, I understand why the `getview()` **should not** provide `Activty` on its parameter, but at least it should have provide `LayoutInflater` which makes coding easier. – Rick Royd Aban Apr 15 '14 at 03:17
  • This is what I was talking about. Fragments, for example, create and provide an UI and you must attach all the views to it. That's why the first parameter is a `LayoutInflater` which it is used for inflate the layout and attach all the elements to the root view thanks to *rootView.findView..*. Whereas an Adapter just attaches itself one to a context, and create multiple views but not an interface. – Blo Apr 15 '14 at 04:08
0

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(...);
        }
        ...
    }
Karakuri
  • 38,365
  • 12
  • 84
  • 104
0

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;
    }

}
Gal Rom
  • 6,221
  • 3
  • 41
  • 33
0

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.

Alexander Kulyakhtin
  • 47,782
  • 38
  • 107
  • 158
  • on my opinion I dont think that adding context as parameter would make it "less abstract". For example, `fragment`'s `onCreateView()` it does provide a `LayoutInflater` on its parameter – Rick Royd Aban Apr 14 '14 at 04:49