57

In many of the code samples that I find on the internet the context is obtained in the constructor of an adapter.

This context is used to get an inflater to inflate the views in getView method.

My Question is why bother getting the context in the constructor when it can easily be obtained like so

        LayoutInflater inflater;
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(inflater == null){
            Context context = parent.getContext();
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }
            ...
            ...

            return convertView;
        }

Also is there any reason not to use the above method because it till now I have not faced any problem in using it .

Gautam
  • 7,444
  • 9
  • 61
  • 102

5 Answers5

40

Obtaining the Context in the constructor has (at least) three advantages:

  1. You only do it once, not every time, getView() is called.
  2. You can use it for other purposes too, when needed.
  3. It also works, when parent is null.

However, if you don't have any problems with your solution, you might as well stick to it.

hata
  • 8,429
  • 5
  • 32
  • 57
Ridcully
  • 22,583
  • 7
  • 66
  • 81
  • 3
    - I don't get the context every time `getView` is called, only when the inflater is null - Personally I have never needed the context anywhere outside `getview` - Parent being null seems rare , but this is a valid point – Gautam Aug 27 '12 at 09:14
4

Here is an example:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    Holder holder;
    if (view == null) {
        view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_job, parent, false);
        holder = new Holder(view, this);
        view.setTag(holder);
    } else {
        holder = (Holder) view.getTag();
    }

    holder.parse(getItem(position), position);
    return view;
}

public class Holder {

    @Bind(R.id.type)
    TextView type;
    @Bind(R.id.date_time)
    TextView dateTime;
    @Bind(R.id.grade)
    TextView grade;

    public Holder(View view) {
        ButterKnife.bind(this, view);
    }

    public void parse(final GetGradeHistoryResponse.GradeHistory item) {
        if (item.grade < 0) {
            grade.setTextColor(App.getInstance()
                    .getResources().getColor(R.color.withdraw_status));
            grade.setText(String.valueOf(item.grade));
        } else {
            grade.setTextColor(App.getInstance()
                    .getResources().getColor(R.color.primary));
            grade.setText("+" + String.valueOf(item.grade));
        }

        type.setText(item.type);
        dateTime.setText(item.datetime);
    }
}

You can get context by view.getContext() in the Holder

wyx
  • 2,476
  • 4
  • 17
  • 37
2

What if someone will create a class that uses BaseAdapter to store Views somewhere (and, maybe, it will attach them to parent later)? In this case parent may be null.

It's not such a big problem, decide for yourself what is better.

For example:

public class MockWithAdapter{

    private BaseAdapter mAdapter;

    public MockWithAdapter(BaseAdapter adapter){
        mAdapter = adapter;
    }

    public List<View> mock(){
        int size = mAdapter.getCount();
        List<View> views = new ArrayList(size);
        for(int i=0; i<size; i++)
            views.add(mAdapter.getView(i, null, null));

        return views;
    }
}

And then you can do with this views whatever you want:

MockWithAdapter m = new MockWithAdapter(adapter);
ListView lv = new ListView(context);
for(View v : m.mock)
    lv.addView(v);
Dmitry Zaytsev
  • 22,662
  • 13
  • 89
  • 139
  • That is actually an interesting point, but can you please elaborate with some code so that I can fully understand – Gautam Aug 27 '12 at 07:42
  • 1
    In the presentation by `Romain Guy` and `Adam Powell`, They advice against using a local view cache http://dl.google.com/googleio/2010/android-world-of-listview-android.pdf – Gautam Aug 27 '12 at 08:46
  • 2
    @GautamK it's just an example. `MockWithAdapter` is pointless. However, as you can see, situation that `parent` null is possible. If you want more real example - here it is: let's assume that you draw each view to separate bitmap (instead of adding them to `ListView`). – Dmitry Zaytsev Aug 27 '12 at 08:53
2

Just simple like this!!

class RecentlyAdapter(var data: List<String>) : Adapter<RecentlyAdapter.HomeViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val view = inflater.inflate(R.layout.card_recently_played, parent, false)
    return HomeViewHolder(view)
}

override fun getItemCount(): Int {
    return data.size
}

override fun onBindViewHolder(holder: HomeViewHolder, position: Int) {

}

class HomeViewHolder(itemView: View): ViewHolder(itemView) {
    init {
        itemView.setOnClickListener {
            val intent = Intent(itemView.context, MusicPlayerActivity::class.java)
            var context = itemView.context
            context.startActivity(intent)
        }
    }
}

}

To get context use itemView.context

Prakash Reddy
  • 631
  • 6
  • 18
Exel Staderlin
  • 467
  • 6
  • 9
0

Yes but if you need any activity reference like for example dialog alert you cannot use context reference , therefore constructor should receive activity reference from calling Activity/Fragment

Prakash Reddy
  • 631
  • 6
  • 18