简体   繁体   English

从 ViewHolder 获取适配器实例

[英]Getting an adapter instance from a ViewHolder

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.我正在尝试创建一个上下文浮动菜单,其中包含可在我的 Fragment 中的重写方法onContextItemSelected中访问的所选菜单的信息(位置、ID 等)。

So I have a custom adapter extending from RecyclerView.Adapter<ViewHolder> and a custom ViewHolder class in separate file.所以我有一个从RecyclerView.Adapter<ViewHolder>扩展的自定义适配器和一个单独文件中的自定义ViewHolder类。 I registered my click listener and provided its handler inside the custom ViewHolder class.我注册了我的点击监听器并在自定义ViewHolder类中提供了它的处理程序。

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 .由于我需要在触发事件时将ViewHolder信息发送回我的 Fragment,因此我需要对我的 Adapter 进行引用,因为我的片段具有adapter object reference但没有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 .因此,在自定义ViewHolder实例化阶段(因为没有从ViewHolder类获取适配器引用的方法),我将适配器引用传递给自定义ViewHolder构造函数以在其处理程序中使用,因此我可以在ViewHolder类中调用此引用将信息从ViewHolder传递给Adapter ,最后从Adapter传递给Fragment

My question is, is there a better practice or a general approach by still keeping the handler inside the ViewHolder ?我的问题是,将处理程序保留在ViewHolder是否有更好的做法或通用方法? In my case, I notice every ViewHolder instance will have to keep a reference to adapter, which consumes memory.就我而言,我注意到每个 ViewHolder 实例都必须保留对适配器的引用,这会消耗内存。 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. Fragmen 知道适配器引用,而适配器知道您的查看器。 Use getAdapterPosition() to get that reference to your Object使用getAdapterPosition()获取对您的对象的引用

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假设在您的RecyclerView.Adapter<ViewHolder>有一个ArrayList<String>命名列表:例如,此代码在 Fragment 中显示了一个 Toast,其中包含单击的 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假设您有一个带有名称、价格、地址等变量的 ItemObjects 类

  1. ViewHolder as external class: ViewHolder 作为外部类:

In the Adapter, attach the ArrayList as Tag to the layoutView :在 Adapter 中,将 ArrayList 作为 Tag 附加到 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:然后,在 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.将 ViewHolder 作为内部类移回适配器中。 This way you can access the ArrayList directly :这样您就可以直接访问 ArrayList :

     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.就我而言,我启动了一个 Activity onClick 并且两个变体都有效。 In your case it would be better to use an inner class and access it through MyRecyclerViewAdapter.MyViewHolders在您的情况下,最好使用内部类并通过 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.您可以在 Blake 提到的视图持有者构造函数中传递适配器。 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.但是,如果视图持有者类是适配器的内部类,则您可以直接访问适配器的方法而无需传递引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法从ViewHolder(RecyclerView)调用适配器中的方法 - Unable to call method in Adapter from ViewHolder (RecyclerView) 从片段访问内部类方法(来自适配器的Viewholder) - Access Inner Class Method (from Viewholder in adapter) from a Fragment ListView适配器中的ViewHolder无法正常工作 - ViewHolder in ListView adapter not working 自定义适配器ViewHolder问题 - Custom Adapter ViewHolder issue 从适配器外部更改 RecyclerView.ViewHolder 布局 - Change RecyclerView.ViewHolder Layout from outside Adapter 无法从 ViewHolder (RecycleView) 调用 Adapter(onBindViewHolder) 中的方法 - Unable to call method in Adapter(onBindViewHolder) from ViewHolder (RecycleView) ListFragment适配器的通用Viewholder类型 - generic viewholder type for a ListFragment adapter 来自Fragment的Adapter的ViewHolder启动Activity,Activity如何与Fragment对话? - ViewHolder from Adapter from Fragment starts Activity, how can the Activity talk back to the Fragment? Android:使用ViewHolder,OnCheckedChangedListener和TextChangedListener的自定义适配器 - Android: Custom Adapter with ViewHolder, OnCheckedChangedListener and TextChangedListener 在Custom Listview Adapter android中使ViewHolder最终化 - making ViewHolder final in Custom Listview Adapter android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM