日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑

發布時間:2025/3/20 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

RecyclerView中EditText和ImageView的ViewHolder復用坑

RecyclerView作為ListView的升級版,目前來講講開發過程遇到的坑。

  • RecyclerView 中使用 EditText 滾動后數據消失,錯亂
    場景:RecyclerView中的每個Item的ViewHolder布局中為都有EditText控件,且ViewHolder實現文本改變監聽器TextWatcher,用來在用戶輸入后將數據取出寫入到 列表數據中。
    添加文本后,上下滑動RecyclerView且將Item劃出屏幕。如:填寫此EditText為1后,滑出屏幕滑回,文本可能變成0后或其他

    結果:對應位置上的EditText未能顯示Adapter數據集中對應位置的Text
/*recyclerview優化的holder*/public static abstract class BaseViewHolder<Data> extends RecyclerView.ViewHolder{/*** 構造** @param itemView 初始化根布局*/public BaseViewHolder(View itemView) {super(itemView);/*不設置,itemview不會鋪滿屏幕*/itemView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,RecyclerView.LayoutParams.WRAP_CONTENT));}/*** 適配器刷新子項回調* @param data*/public abstract void onRefreshView(Data data,int position);public final <T> T findViewById(int resId){return (T) itemView.findViewById(resId);}} /*ViewHolder*/public class ViewHolderContentText extends RecyclerViewBaseAdapter.BaseViewHolder<ArticleContentBean> implementsTextWatcher, {private static final int VIEW_TYPE=3;/*編輯框*/public EditText contentText;public ViewHolderContentText(View itemView) {super(itemView);contentText= (EditText) itemView.findViewById(R.id.et_text);quoteLine=itemView.findViewById(R.id.v_quote_line);/*設置文本改變監聽器*/contentText.addTextChangedListener(this);}@Overridepublic void onRefreshView(ArticleContentBean articleContentBean, int position){/*刷新數據*/String text=textBean.getContentText();contentText.setText(text);}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {/*將寫入EditText的文本保存到Adapter的DataList中*/} }

原因
????乍一看這段代碼沒有什么問題,但實際上這里有一個很大的坑。通過在 afterTextChanged 方法上增加 Log 記錄可以發現,該方法會被多次的調用,其根本原因是因為 EditText 的被重新復用,并且重新繪制!當重繪之后 該回調函數沒有獲取到填充的數據,還是原來復用的數據。

解決辦法:每次填充數據之前先移除 TextWatcher 監聽器,然后為 EditText 填充數據 ,最后在為 EditText 添加 TextWatcher 監聽器,

/*ViewHolder*/public class ViewHolderContentText extends RecyclerViewBaseAdapter.BaseViewHolder<ArticleContentBean> implementsTextWatcher, {private static final int VIEW_TYPE=3;/*編輯框*/public EditText contentText;public ViewHolderContentText(View itemView) {super(itemView);contentText= (EditText) itemView.findViewById(R.id.et_text);quoteLine=itemView.findViewById(R.id.v_quote_line);/*設置文本改變監聽器*///contentText.addTextChangedListener(this);}@Overridepublic void onRefreshView(ArticleContentBean articleContentBean, int position){/*** recyclerview中使用editext導致數據混亂情況:必須這樣設置TextWatcher* *///1,為了避免TextWatcher在第2步被調用,提前將他移除if (contentText.getTag(R.id.tag_textWatcher_data) instanceof TextWatcher){contentText.removeTextChangedListener(this);}//2,移除TextWatcher之后,設置EditText的Text。String text=textBean.getContentText();contentText.setText(text);//3,重新添加 TextWatcher 監聽器contentText.addTextChangedListener(this);//4,將TextWatcher綁定到EditTextcontentText.setTag(R.id.tag_textWatcher_data,this);}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {/*將寫入EditText的文本保存到Adapter的DataList中*/} }
  • RecyclerView 中使用 ImageView滾動后圖片閃爍,圖片切換明顯

場景
????RecyclerView 的Item布局中都包含ImageView,加載圖片使用Glide加載,當ImageView填充圖片之后,滑出屏幕在滑回,回看見圖片回閃一下,或者先顯示上一張圖片瞬間切換到應該顯示的圖片,切換明顯
原因
????因為RecyclerView 的ViewHolder復用,當顯示該圖片時,在RecyclerView 的holder復用池中取出一個之前的Holder顯示該圖片,但是此Holder還持有之前的圖片,所以如果該圖片和此Holder持有的圖片相同就閃爍,不同就會有明顯的切換。

解決方案
????將數據綁定到ViewHolder的Tag,當刷新數據時,判斷此ViewHolder的Tag的之前綁定的數據與當前數據比較,相同就不刷新數據,不相同就使用Glide的placeholder墊一個白色或無色圖

/*ViewHolder 圖片*/public class ViewHolderContentPhoto extends RecyclerViewBaseAdapter.BaseViewHolder<ArticleContentBean> {private static final int VIEW_TYPE=4;/*圖片*/public ImageView contentPhoto;public ViewHolderContentPhoto(View itemView) {super(itemView);contentPhoto= findViewById(R.id.iv_insert_photo);}@Overridepublic void onRefreshView(final ArticleContentBean articleContentBean, final int position) {/*防止holder重用,數據重加載,閃爍問題*/ArticleContentBean dataBefore= contentPhoto.getTag(R.id.tag_item_data);if (dataBefore!=null&&dataBefore.equals(articleContentBean)){return;}String path = dataBefore.getPath();//glide加載圖片Glide.with(context).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).crossFade()/*placeholder占位,防holder復用,出現圖片切換現象*/.placeholder(new ColorDrawable(Color.TRANSPARENT)).into(contentPhoto);//將數據綁定到viewholdercontentPhoto.setTag(R.id.tag_item_data,articleContentBean);}}


參考鏈接:
1.踩坑記-在 RecyclerView 中使用 EditText 滾動后數據消失
2. RecyclerView中使用EditText
3.小心!Listview結合EditText使用實例中遇到的那些坑

總結

以上是生活随笔為你收集整理的Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。