繁体   English   中英

RecyclerView 适配器中的匿名侦听器

[英]Anonymous Listener in RecyclerView Adapter

编辑:

我想知道在bindViewHolder方法中创建匿名侦听器会导致任何性能问题或不会导致大型数据集。

假设我有一个RecyclerView适配器。 bindViewHolder方法中,如果我匿名设置所有侦听器,这会导致任何性能问题吗? 因为当用户滚动 RecyclerView 时,它会创建许多匿名侦听器并将它们设置为视图。

例子:

view.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View v)
    {
    } 
});

或者我可以在我的 ViewHolder 类中实现OnClickListener并添加到 views.Like

view.setOnClickListener(this);

这里没有创建很多匿名侦听器。 在大型数据集的性能计算中,这是否比以前的性能更好?

提前致谢。

RecyclerView只会显示很少的项目, ViewHolder只会为可见的项目创建,因此即使您的适配器中有 1000 个项目,也只会创建一小部分ViewHolders

但是您必须小心使用addListener方法,对于大多数setListener方法,当项目被回收时,您将一次又一次地设置相同的侦听器,这不会少于几毫秒,因为它只保留侦听器实现的引用。

但是使用addListener ,您必须在添加新侦听器之前删除旧侦听器。

的例子setListenersetClickListener和举例addListeneraddTextWatcher

//.. part of adapter

private TextWatcher textWatcher;

public void bindViewHolder(DataViewHolder holder, int index){

    // no performance issue
    holder.button.setClickListener( .... );

    // wrong, this is added everytime
    holder.editText.addTextWatcher( .... );


    // this is safe...
    if(textWatcher != null)
       holder.editText.removeTextWatcher(textWatcher);

    textWatcher = new TextWatcher(){
       // ... implementation
    };
    holder.editText.addTextWatcher(textWatcher);
}

基本上,您在RecyclerView每个项目中设置一个OnClickListener并将其“连接”到您的ActivityFragment 这种“连接”很重要,因此您可以在ActivityFragment使用onItemClick方法并访问那里的成员。

最小的实现如下所示(在Fragment ,但您也可以使用Activity ):

public class YourFragment extends Fragment implements RecyclerViewAdapter.ItemClickListener {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View view = inflater.inflate(R.layout.fragment_your, container, false);

        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
        RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(activity);
        recyclerViewAdapter.setClickListener(this);
        recyclerView.setAdapter(recyclerViewAdapter);

        return view;
    }

    @Override
    public void onItemClick(View view, int position) {
        // do something here
    }
}

Adapter

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    private ItemClickListener itemClickListener;

    void setClickListener(ItemClickListener itemClickListener) {
        this.itemClickListener = itemClickListener;
    }

    interface ItemClickListener {
    void onItemClick(View view, int position);
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        // TextView is an example
        final TextView textView;

        ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.text);
            textView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (itemClickListener != null) {
                itemClickListener.onItemClick(view, getAdapterPosition());
            }
        }
    }
}

我很确定编译器只是在幕后创建了匿名类的无名具体版本。 这几乎等同于实现该接口并提供this作为一个具体的监听器。 实际上,两者都不应该有性能问题。

请记住,匿名类持有对外部类的引用。 这可能会造成内存泄漏(例如:如果外部类是一个活动)或者只是让垃圾收集一次性发生,而不是随着时间的推移发生小块。 有关更多详细信息,请参阅 oracle 文档中的隐式和合成参数

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM