RecyclerView适配器中的匿名侦听器

时间:2017-09-30 15:27:41

标签: android performance android-recyclerview anonymous-class

编辑:

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

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

示例:

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

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

view.setOnClickListener(this);

这里没有创建很多匿名听众。对于大型数据集,这在以前的性能计算中表现更好吗?

提前致谢。

3 个答案:

答案 0 :(得分:1)

RecyclerView只会显示一些项目,ViewHolder只会为可见的项目创建,所以即使您的适配器中有1000个项目,也只有ViewHolders的一小部分是创造的。

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

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

setListener的示例为setClickListeneraddListener的示例为addTextWatcher

//.. 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);
}

答案 1 :(得分:0)

基本上,您在OnClickListener和" connect"的每个项目中都设置了RecyclerView。它是ActivityFragment。这个"连接"很重要,因此您可以在onItemClickActivity中使用Fragment方法并访问其中的成员。

最小的实现看起来像这样(在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());
            }
        }
    }
}

答案 2 :(得分:0)

我很确定编译器只会在你的匿名类中创建一个无名的具体版本。这几乎与实现接口并将this作为具体监听器相同。实际上,你不应该遇到性能问题。

请记住,匿名类包含对外部类的引用。这可能会造成内存泄漏(例如:如果外部类是一个活动),或者只是让它一次性发生垃圾收集而不是小块。有关详细信息,请参阅oracle文档中的Implicit and Synthetic Parameters