天天看點

android listview 資料加載錯亂、錯位、重複

前言:

android的listview,寫吐了的東西,尤其它的擴充卡,當遇上相對複雜的場景的時候,還是容易出問題的,例如listview嵌套listview這樣的場景、對item中子控件頻繁的做一些操作等,可能會遇到資料加載錯亂、錯位等問題。其實這個時候,你怎麼加斷點加log列印都是沒用的,你會發現資料都是正常的。

正文:

首先必須要明白listview的工作原理:

android為了優化listview,提升系統性能,提供getView方法,其中convertView參數就是來實作優化的。當使用者滑動清單時,原先可視的item被滾出螢幕變得不可視,而代表該行的java對象可以被新的可視行複用。也就是說如果清單在手機螢幕中一屏可見的行有7行,當第一行滑出螢幕時,底部新滑出來的第8行可以複用第1行的java對象(即通過item布局inflate出來的view),Android已經把第一行的布局緩存起來,作為可以複用的convertView。

上述說的對象複用問題,是基于我們的viewHolder的,例如:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.item_loadpic, parent,false);
        viewHolder = new ViewHolder();
        viewHolder.img = (ImageView) convertView.findViewById(R.id.image);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
           

當listview初始化加載資料的時候,會進到getView方法中,如果converView為空,則inflate出一個對象,并且通過setTag方法儲存起來,如果converView不為空,則通過getTag方法取出來。假設你的手機螢幕一次隻能容納7行的資料(當然要視item的height而定),那converView ==null這個判斷會走7次,之後你下拉清單和上拉清單都會走 else ,也就是converView不為空的情況,這也正是listview的強大之處,即便item再多,我也隻建立幾個holder就夠了,省的每次都是findViewById消耗資源了,之後全是複用。

當你遇到資料加載錯亂、重複的問題時,你可能先去檢視代碼,例如:

if (position == 3) {
     viewHolder.rl_title.setBackgroundResource(R.drawable.layout_blue_bg);
    } 
           

怎麼看都沒毛病,就是position == 3的時候,我設定了背景,為啥下面的也是有這樣的背景,會不會是下面的position也有等于3的?别天真,别跟這行代碼較真,看看上面的原理就會明白。

廢話不多說,基本上你所有的資料錯亂的問題,都可以用一個if - else解決:

if (position == 3) {
     viewHolder.rl_title.setBackgroundResource(R.drawable.layout_blue_bg);
    } else{
    viewHolder.rl_title.setBackgroundResource(normal);
    }
           

切記,隻需要一個if-else!

切記,隻需要一個if-else!

切記,隻需要一個if-else!