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?
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();
}
});
}
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
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());
}
}
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
Pass the adapter in the constructor of the view holder
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout, parent, false);
return new MyViewHolder(this, view);
}
You may pass the adapter in the view holder constructor as Blake mentioned. However, if the view holder class is an inner class of the Adapter you may access methods of the adapter directly without needing to pass a reference.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.