1. 程式人生 > >RecyclerView和ListView的複用BUG以及解決辦法

RecyclerView和ListView的複用BUG以及解決辦法

RecyclerView和ListView的複用BUG

  • BUG出現的場景舉例
  • 簡單的介紹複用機制
  • 複用機制BUG的解決方式

BUG出現場景舉例

  • 當想實現listview的多選情況時,滑動出現,checkbox錯亂,也就是沒有選中的被選中了
  • 當listview想要實現點選變色實現閱讀過標記變色時,滑動後出現未閱讀的也變色了

複用機制的簡單介紹

  • 當listView每要展示一個item的時候就會向adapter索要一個view,也就是呼叫adapter的getView()方法
 @Override
        public View getView(int
position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.item1, null); holder = new ViewHolder(); holder.textView = (TextView)convertView.findViewById(R.id.text); convertView.setTag(holder); } else
{ holder = (ViewHolder)convertView.getTag(); } holder.textView.setText(mData.get(position)); return convertView; }

上面列出baseadapter中getView的常用寫法,如果我們先不看converview,那麼每呼叫一次getview方法,getview方法就會inflater一次,如果有很多item,那這個方法就會呼叫很多次,inflater又是一個IO操作,是非常消耗資源的,所以google給我們提供了Recycler機制,getView(int position, View convertView, ViewGroup parent),converView就是Recycler為我們快取之前的item,

  • 第一點:Recycler中最多有幾個快取? 快取個數=螢幕可見ite數+itemType個數
  • 第二點:從第幾個item開始開始複用converview? 很多人在剛接觸的時候會以為是在 螢幕可見item數+1 個item時候使用converView, 但實際上是在
    螢幕可見item數+3 個item是複用第1個item ,
    螢幕可見item數+4 個item是複用第2個item ,
    螢幕可見item數+5 個item是複用第3個item ,
    螢幕可見item數+6 個item是複用第4個item ,
  • 第三點 :因為我們在建立每一個item的時候都對item中的每一個控制元件賦予了不同的內容,所以我們很難了解,所以這裡我們只對 螢幕可見item數+1 個item進行賦予內容(因為螢幕可見item數+3時就複用第一個item了。所以我們不給它賦予內容,因為我的模擬器螢幕可見item數是4,所以我的判斷條件是position<6)
if (position<6){
                boolean hasRead = CasheUtils.getBooble(activity, news.get(position).id + "", false);
                viewHolder.date.setText(news.get(position).pubdate);
                viewHolder.title.setText(news.get(position).title);
                if (hasRead){
                    viewHolder.title.setTextColor(Color.GRAY);
                }else {
                    viewHolder.title.setTextColor(Color.BLACK);
                }
                ImageLoader.getInstance().displayImage(Constants.BASE_URL + news.get(position).listimage, viewHolder.newsIcon);
                if (position%3==0){
                    convertView.setBackgroundColor(Color.GREEN);
                }
            }

這裡寫圖片描述

在這裡大家可以看到這裡完全可見item數目為4,但是第一條還是可見的,最上面的綠邊是第一條item的底部,最後一條露出了一小半,也就是第六條也是可見的,這時候converView是空的,這也就是為什麼不是在 螢幕可見item數+1和螢幕可見item數+2時候使用converView而是在螢幕可見item數+3的時候複用converView,因為像這樣,螢幕可見item數+1 只顯示一半的時候 第一個item還未進入Recycler中,也就是converView為空,不能複用。
因為我們只給前5個item進行了賦予內容,螢幕可見item數+1 賦予了內容,剛好在螢幕可見item數+2的時候複用converView, 按照之前說的,螢幕可見item數+2複用第一個item,那我們來看一個第七個item是否和第一個item內容一樣

下面是1-5個item圖片
這裡寫圖片描述

接下來是5-8的item圖片
這裡寫圖片描述
這裡大家可以看到第七條和第一條一模一樣,第八天和第二條一模一樣,正式因為這樣,所以才會出現 在實現多選時,如果滑動了,沒有選中的item也會被選中,因為getview()的時候沒有對checkbox進行狀態設定,也就是第七個item的checkbox直接複用了第一個item的checkbox的狀態,這個道理同樣適用於閱讀標記功能,一樣的也適用於recyclerview控制元件上

解決辦法

就是同item中間中其他控制元件(textView等等)一樣,在get每一個itemView的時候對checkBox進行狀態賦值,以及閱讀標記