日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

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

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

RecyclerView中EditText和ImageView的ViewHolder復(fù)用坑

RecyclerView作為L(zhǎng)istView的升級(jí)版,目前來講講開發(fā)過程遇到的坑。

  • RecyclerView 中使用 EditText 滾動(dòng)后數(shù)據(jù)消失,錯(cuò)亂
    場(chǎng)景:RecyclerView中的每個(gè)Item的ViewHolder布局中為都有EditText控件,且ViewHolder實(shí)現(xiàn)文本改變監(jiān)聽器TextWatcher,用來在用戶輸入后將數(shù)據(jù)取出寫入到 列表數(shù)據(jù)中。
    添加文本后,上下滑動(dòng)RecyclerView且將Item劃出屏幕。如:填寫此EditText為1后,滑出屏幕滑回,文本可能變成0后或其他

    結(jié)果:對(duì)應(yīng)位置上的EditText未能顯示Adapter數(shù)據(jù)集中對(duì)應(yīng)位置的Text
/*recyclerview優(yōu)化的holder*/public static abstract class BaseViewHolder<Data> extends RecyclerView.ViewHolder{/*** 構(gòu)造** @param itemView 初始化根布局*/public BaseViewHolder(View itemView) {super(itemView);/*不設(shè)置,itemview不會(huì)鋪滿屏幕*/itemView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,RecyclerView.LayoutParams.WRAP_CONTENT));}/*** 適配器刷新子項(xiàng)回調(diào)* @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);/*設(shè)置文本改變監(jiān)聽器*/contentText.addTextChangedListener(this);}@Overridepublic void onRefreshView(ArticleContentBean articleContentBean, int position){/*刷新數(shù)據(jù)*/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中*/} }

原因
????乍一看這段代碼沒有什么問題,但實(shí)際上這里有一個(gè)很大的坑。通過在 afterTextChanged 方法上增加 Log 記錄可以發(fā)現(xiàn),該方法會(huì)被多次的調(diào)用,其根本原因是因?yàn)?EditText 的被重新復(fù)用,并且重新繪制!當(dāng)重繪之后 該回調(diào)函數(shù)沒有獲取到填充的數(shù)據(jù),還是原來復(fù)用的數(shù)據(jù)。

解決辦法:每次填充數(shù)據(jù)之前先移除 TextWatcher 監(jiān)聽器,然后為 EditText 填充數(shù)據(jù) ,最后在為 EditText 添加 TextWatcher 監(jiān)聽器,

/*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);/*設(shè)置文本改變監(jiān)聽器*///contentText.addTextChangedListener(this);}@Overridepublic void onRefreshView(ArticleContentBean articleContentBean, int position){/*** recyclerview中使用editext導(dǎo)致數(shù)據(jù)混亂情況:必須這樣設(shè)置TextWatcher* *///1,為了避免TextWatcher在第2步被調(diào)用,提前將他移除if (contentText.getTag(R.id.tag_textWatcher_data) instanceof TextWatcher){contentText.removeTextChangedListener(this);}//2,移除TextWatcher之后,設(shè)置EditText的Text。String text=textBean.getContentText();contentText.setText(text);//3,重新添加 TextWatcher 監(jiān)聽器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滾動(dòng)后圖片閃爍,圖片切換明顯

場(chǎng)景
????RecyclerView 的Item布局中都包含ImageView,加載圖片使用Glide加載,當(dāng)ImageView填充圖片之后,滑出屏幕在滑回,回看見圖片回閃一下,或者先顯示上一張圖片瞬間切換到應(yīng)該顯示的圖片,切換明顯
原因
????因?yàn)镽ecyclerView 的ViewHolder復(fù)用,當(dāng)顯示該圖片時(shí),在RecyclerView 的holder復(fù)用池中取出一個(gè)之前的Holder顯示該圖片,但是此Holder還持有之前的圖片,所以如果該圖片和此Holder持有的圖片相同就閃爍,不同就會(huì)有明顯的切換。

解決方案
????將數(shù)據(jù)綁定到ViewHolder的Tag,當(dāng)刷新數(shù)據(jù)時(shí),判斷此ViewHolder的Tag的之前綁定的數(shù)據(jù)與當(dāng)前數(shù)據(jù)比較,相同就不刷新數(shù)據(jù),不相同就使用Glide的placeholder墊一個(gè)白色或無色圖

/*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重用,數(shù)據(jù)重加載,閃爍問題*/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復(fù)用,出現(xiàn)圖片切換現(xiàn)象*/.placeholder(new ColorDrawable(Color.TRANSPARENT)).into(contentPhoto);//將數(shù)據(jù)綁定到viewholdercontentPhoto.setTag(R.id.tag_item_data,articleContentBean);}}


參考鏈接:
1.踩坑記-在 RecyclerView 中使用 EditText 滾動(dòng)后數(shù)據(jù)消失
2. RecyclerView中使用EditText
3.小心!Listview結(jié)合EditText使用實(shí)例中遇到的那些坑

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。