Context for RecyclerView.Adapter

10,649

Solution 1

I've seen a lot of code where people keep reference to the Context in an Adapter. But in a RecyclerView.Adapter, the itemView (the view you already inflated from onCreateViewHolder) is accessible from your ViewHolder. For the most part, you should be dealing with the viewHolder anyways. So, use viewholder.itemView.getContext();. You can even expose a method in your viewholder getContext().

public Context getContext() {return itemView.getContext();}

Solution 2

Firstly, there are some differences between type of Contexts. Reference: https://possiblemobile.com/2013/06/context/

Example:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
     return new ViewHolder(v);
} 

@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    Context context = viewHolder.anyView.getContext();
}

Solution 3

Create a custom Adapter and add a Constructor so that the Context can be passed.

public class CustomAdapter extends ArrayAdapter<String> {

    private Context context;
    private List<String> stringList = null;

    public CustomAdapter(Context context, int resource, List<String> objects) {
        super(context, resource, objects);
        this.context = context;
        this.stringList = objects;
    }
}

Use this 'context' variable to show the ProgressDialog as per your requirement.

Solution 4

1.Pass activity context in constructor for adapter. if your calling from fragment pass it as getActivity().

2.You can also try itemView.getContext() in onBindViewHolder.

I am not sure about pros and cons of using #2 method because I always use #1.

Solution 5

In fragment add:

Context context;
#in onCreateView method:
context=getActivity();
allGroupsView = (RecyclerView) rootView.findViewById(R.id.allGroupsView);
adapterGroup = new AdapterGroup(context,results);
allGroupsView.setAdapter(adapterGroup);
allGroupsView.setLayoutManager(new LinearLayoutManager(getActivity()));

dont use getActivity.getApplicationContext() or context.getApplicationContext()

loading = ProgressDialog.show(mContext, null, "Please wait", true, true);
Share:
10,649
August
Author by

August

Updated on June 09, 2022

Comments

  • August
    August about 2 years

    I want to add ProgressDialog in an adapter. AFAIK, .this for activity, and getActivity.getApplicationContext() for fragment. What about adapter? Is it possible?

    I got error Unable to add window -- token null is not valid; is your activity running? when I use mContext.getApplicationContext().

    EDIT:

    In a fragment, I show cards by

    allGroupsView = (RecyclerView) rootView.findViewById(R.id.allGroupsView);
    adapterGroup = new AdapterGroup(getActivity().getApplicationContext(), results);
    allGroupsView.setAdapter(adapterGroup);
    allGroupsView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
    

    In class AdapterGroup

    public class AdapterGroup extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
    private Context mContext;
    private LayoutInflater inflater;
    List<DataGroup> data= Collections.emptyList();
    DataGroup current;
    
    public AdapterGroup(Context context, List<DataGroup> results) {
        this.mContext = context;
        inflater = LayoutInflater.from(mContext);
        this.data = results;
    }
    
    // Inflate the layout when viewholder created
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.card_view_row, parent, false);
        final MyHolder holder = new MyHolder(view);
    
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("debug", String.valueOf(holder.getAdapterPosition()));
                getDetails(Config.GET_GROUP_DETAILS_URL, data.get(holder.getAdapterPosition()).groupName, data.get(holder.getAdapterPosition()).description);
            }
        });
    
        return holder;
    }
    
    private void getDetails(String url, String groupName, String description) {
    
        groupName = groupName.replace(" ", "%20");
        description = description.replace(" ", "%20");
    
        final String finalGroupName = groupName;
        final String finalDescription = description;
    
        class GetDetails extends AsyncTask<String, Void, String> {
            ProgressDialog loading;
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(mContext.getApplicationContext(), null, "Please wait", true, true);
                loading.setCancelable(false);
            } // more code down from here
    
  • OneCricketeer
    OneCricketeer over 7 years
    Question asked about RecyclerView.Adapter. Besides, storing the context member variable in a ArrayAdapter is redundant.
  • vidulaJ
    vidulaJ over 7 years
    You can use this for a RecyclerView Adapter as well.
  • OneCricketeer
    OneCricketeer over 7 years
    Sure. I think the question already is doing this, though, as mContext appears to be the variable in the adapter and mContext.getApplicationContext is throwing an exception
  • vidulaJ
    vidulaJ over 7 years
    Did not have the code previously and the edit had been done after this answer. So using only mContext, a ProgressDialog could be started.
  • August
    August over 7 years
    if I use mContext only without getApplicationContext it also throw the same exception
  • OneCricketeer
    OneCricketeer over 7 years
    @August That may be because you also assigned mContext with a call to getApplicationContext when you initialized the adapter.
  • vidulaJ
    vidulaJ over 7 years
    You initialize Adapter variable inside a Fragment?
  • August
    August over 7 years
    can you please take a look at my newly added codes?
  • August
    August over 7 years
    Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
  • WritingForAnroid
    WritingForAnroid over 7 years
    By seeing updated code I feel its better to pass context in constructor.