簡體   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