Getting an adapter instance from a ViewHolder

我与影子孤独终老i 提交于 2020-03-06 03:33:30

问题


I'm trying to create a contextual floating menu with the information (position,id,etc) of the selected menu to be accessible inside the overridden method onContextItemSelected in my Fragment.

So I have a custom adapter extending from RecyclerView.Adapter<ViewHolder> and a custom ViewHolder class in separate file. I registered my click listener and provided its handler inside the custom ViewHolder class.

Since I need to send the ViewHolder information back to my Fragment when the event is fired, I need to have a reference to my Adapter because my fragment has the adapter object reference but not viewholder object reference. So in instantiation stage of the custom ViewHolder (because there is no method to get Adapter reference from ViewHolder class), I pass the adapter reference to constructor of the custom ViewHolder for the use in its handler so I can call this reference inside the ViewHolder class to pass the information to Adapter from ViewHolder, and finally from Adapter to Fragment.

My question is, is there a better practice or a general approach by still keeping the handler inside the ViewHolder? In my case, I notice every ViewHolder instance will have to keep a reference to adapter, which consumes memory. Is there any conflict that may arise in the future by doing it the way I listed above?


回答1:


Maybe I'm not understanding well your pattern, but the reference you are looking for, it is already there.

The fragmens knows the adapter reference, and the adapter knows your viewholder. Use getAdapterPosition() to get that reference to your Object

Suppose to have a ArrayList<String> named list in your RecyclerView.Adapter<ViewHolder>: this code, for example, shows a Toast in the Fragment with the value of the clicked String

public ViewHolder( View itemView) {

    super(itemView);

    itemView.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            String myValue = list.get( getAdapterPosition() ); // your object 
            Toast.makeText(activity, myValue, Toast.LENGTH_SHORT).show();
        }
    });

}



回答2:


Stumbled upon the same problem. The two variants give the same result, without using static references:

Suppose you have an ItemObjects class with name, price, address etc variables

  1. ViewHolder as external class:

In the Adapter, attach the ArrayList as Tag to the layoutView :

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyViewHolders> {

private List<ItemObjects> itemList;
private Context context;

public MyRecyclerViewAdapter(Context context, List<ItemObjects> itemList) {
    this.itemList = itemList;
    this.context = context;
}

@Override
public MyViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {

    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_list_cell, parent, false);
    layoutView.setTag(itemList);
    return new MyViewHolders(layoutView);
}
}

Then, in the ViewHolder:

public class MyViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener {

public MyViewHolders(View itemView) {
    super(itemView);
    itemView.setOnClickListener(this);
    //................
 }

@Override
public void onClick(View view) {

    Log.d(TAG, "onClick: itemName " + ((ArrayList<ItemObjects>) itemView.getTag())
            .get(getAdapterPosition()).getItemName());
 }
}
  1. Move the ViewHolder back as inner class into the Adapter. This way you can access the ArrayList directly :

    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolders> {
    
    
     private static List<ItemObjects> itemList;
     //........................
    
    
     public static class MyViewHolders extends RecyclerView.ViewHolder 
        implements View.OnClickListener {
      //.......................
    
      @Override
      public void onClick(View view) {
        Intent intent = new Intent(view.getContext(), DetailActivity.class);
    
        Log.d(TAG, "onClick: itemName " +  itemList.get(getAdapterPosition()).getItemName());
        view.getContext().startActivity( new Intent(view.getContext(), DetailActivity.class));
    
       }
      }
      }
    

    In my case, i start an Activity onClick and both variants work. In your case it would be better to use an inner class and access it through MyRecyclerViewAdapter.MyViewHolders



来源:https://stackoverflow.com/questions/37652084/getting-an-adapter-instance-from-a-viewholder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!