2010-06-25 40 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