4

I need to use context methods within the onBindViewHolder (a standard example might be something as common as getString or getColor). Until now I've passed the context to the constructor for the recyclerview and maintained a reference in a variable, however this seems to me to be bad practice. Is there a way of getting context dynamically from inside a recyclerview without storing it as a variable?

public SomeRecyclerViewClass(Activity activity) {
    this.parentActivity = activity;
}
Jon
  • 7,941
  • 9
  • 53
  • 105
  • 1
    You don't need to pass the activity, just pass the context. – Kistamushken Oct 14 '15 at 08:38
  • @Kistamushken thanks - but you mean that in any case I need to pass *something* - there's no way of not passing and storing a reference? – Jon Oct 14 '15 at 08:39
  • 2
    there is nothing wrong with passing context to your adapter. You just should keep your adapter responsible for work with views, leaving networking or database operations for your fragment. – Kistamushken Oct 14 '15 at 09:08

3 Answers3

3

I cannot see any downside of passing the Context in the constructor and store it in a field. Anyway you could access it in this way:

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        //Do your things
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Context context = holder.itemView.getContext();
        //Do your things
    }
}

Just for completeness, I post the solution I usually adopt which keeps also a reference to the LayoutInflater:

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {

    public Context mContext;
    public LayoutInflater mInflater;

    public MyAdapter(Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mInflater.inflate(R.layout.row, parent, false);
        //Do your things
    }
}
rciovati
  • 27,603
  • 6
  • 82
  • 101
  • 1
    Thanks - just what I need. Now there's no class level variable holding a reference to the context – Jon Oct 14 '15 at 08:54
  • 1
    @Jon I think the latter solution is smarter. Because `onCreateViewHolder` and `onBindViewHolder` are called many times. So Riccardo Ciovati may know this that he himself doesn't use the former one. – hata Oct 14 '15 at 09:45
  • Thanks @hata. I posted the latter because I think its the smarter. – rciovati Oct 14 '15 at 10:20
1

You could have a context in application class and can have a static method to get that context.

public class MyApp extends android.app.Application {

private static MyApp instance;

public MyApp() {
    instance = this;
}

public static Context getContext() {
    return instance;
}}
Nishant
  • 575
  • 4
  • 15
  • that's true and I thought of doing that, but in some cases I need to call actual methods that belong to the parent activity/parent fragment and then I can't get to them through application context. – Jon Oct 14 '15 at 08:44
  • In that case, you can check this answer. It might help you. http://stackoverflow.com/questions/12320857/how-to-get-my-activity-context – Nishant Oct 14 '15 at 08:50
  • Does this differ from getApplicationContext() ? – Tim Oct 14 '15 at 08:50
  • Based on answer here http://stackoverflow.com/a/6760019/1375020 , it may differ from getApplicationContext() but should be same as getApplication() – Nishant Oct 14 '15 at 09:01
1

You can do like this :

private Context context;

@Override
    public MessageViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_message_pictures, null);

        context = v.getContext();

        return new MessageViewHolder(v);
    }
Vipul Asri
  • 8,903
  • 3
  • 46
  • 71
  • This is almost perfect for me. Now I don't have to pass in a context, but I still have to store a reference to it, which could theoretically cause a memory leak (?) – Jon Oct 14 '15 at 08:52
  • 2
    No, I don't think so that will cause memory leak as this context will be available only till your Recycler View Adapter is in memory or Recycler View is in current displaying view. – Vipul Asri Oct 14 '15 at 08:54
  • @Jon I think a possibility of memory leak comes when you use `ApplicationContext`. A normal Activity's `Context` is safe as vipul_asri said. So I wouldn't use `ApplicationContext` without special reason. – hata Oct 14 '15 at 09:52