2010-06-25 45 views
9

我遇到了一些BaseAdapter代碼的問題,這些代碼是我從一本書改編而來的。我一直在我的應用程序的各處使用這些代碼的變體,但只有在滾動長列表時才意識到ListView中的項目變得混亂,而不是顯示所有元素。BaseAdapter導致ListView在滾動時出現故障

描述確切的行爲非常困難,但是很容易看出您是否將50個項目排序並開始滾動上下滾動。

class ContactAdapter extends BaseAdapter { 

    ArrayList<Contact> mContacts; 

    public ContactAdapter(ArrayList<Contact> contacts) { 
     mContacts = contacts; 
    } 

    @Override 
    public int getCount() { 
     return mContacts.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     return mContacts.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View view; 
     if(convertView == null){ 
      LayoutInflater li = getLayoutInflater(); 
      view = li.inflate(R.layout.groups_item, null); 
      TextView label = (TextView)view.findViewById(R.id.groups_item_title); 
      label.setText(mContacts.get(position).getName()); 
      label = (TextView)view.findViewById(R.id.groups_item_subtitle); 
      label.setText(mContacts.get(position).getNumber()); 
     } 
     else 
     { 
      view = convertView; 
     } 
     return view; 
    } 

} 

回答

12

您只在第一次創建時將數據放入TextView小部件中。你需要將這些四行:

 TextView label = (TextView)view.findViewById(R.id.groups_item_title); 
     label.setText(mContacts.get(position).getName()); 
     label = (TextView)view.findViewById(R.id.groups_item_subtitle); 
     label.setText(mContacts.get(position).getNumber()); 

if/else塊之後和方法返回之前,讓你更新TextView部件無論您是回收行或創建一個新的一個。

+0

哦另一個很好的例子,我明白了。那麼ListView最多隻包含填充屏幕所需的視圖數量? – 2010-06-25 22:58:21

+0

@Mr。不明確:或多或少。它可以緩存一對能夠快速響應滾動請求。但是,在一個帶有10行UI空間和1000行「適配器」的ListView中,「視圖」的數量將會比1,000更接近10。大概就像12或14一樣。這是'convertView'行回收的重點,所以Android不必創建(以及後來的GC)一堆行部件。 – CommonsWare 2010-06-25 23:31:52

5

爲了進一步澄清CommonsWare的答案,這裏是更多的一些信息:

li.inflate操作(這裏需要從XML行的佈局解析和創建適當的視圖對象)包含if(convertView == null)聲明效率,所以同一對象的通貨膨脹不會一次又一次地發生,每次它彈出視圖。

但是,getView方法的其他部分用於設置其他參數,因此如果(convertView == null){} ... else {}聲明不應包含在之內。

在許多常見的實現該方法的,一些TextView的標籤,或ImageView的元素的ImageButton需要由值從列表[位置]填充,使用findViewById,之後.setText.setImageBitmap操作。 這些操作必須在之後通過通貨膨脹從頭開始創建一個視圖,如果不爲空(例如,在刷新時),則獲得現有視圖。

其中該溶液被應用於一個ListView ArrayAdapter出現在https://stackoverflow.com/a/3874639/978329