【问题标题】:BaseAdapter causing ListView to go out of order when scrolledBaseAdapter 导致 ListView 在滚动时出现故障
【发布时间】:2010-06-25 20:16:12
【问题描述】:

我在使用从书中改编的一些 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;
    }

}

【问题讨论】:

    标签: android listview


    【解决方案1】:

    您仅在首次创建 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 小部件。

    【讨论】:

    • 哦,我明白了。所以 ListView 最多只包含填满屏幕所需的 View 数量?
    • @Mr.模棱两可:或多或少。它可能会缓存一对以便能够快速响应滚动请求。但是,在具有 10 行 UI 空间的 ListView 和 1,000 行的 Adapter 中,Views 的数量将远远接近 10 而不是 1,000。可能像 12 或 14。这就是 convertView 的行回收点,因此 Android 不必创建(以及后来的 GC)一大堆乱七八糟的行小部件。
    【解决方案2】:

    为了进一步澄清 CommonsWare 的答案,这里有更多信息:

    li.inflate 操作(这里需要从 XML 解析行的布局并创建适当的 View 对象)由 if (convertView == null) 声明效率,因此同一对象的膨胀不会在每次出现时一次又一次地发生。

    但是,getView 方法的其他部分用于设置其他参数,因此不应包含在 if (convertView == null){ }... else{ } 语句中。

    在此方法的许多常见实现中,一些 textView 标签、ImageView 或 ImageButton 元素需要使用 list[position] 中的值填充,使用 findViewById 和之后 .setText 或 .setImageBitmap 操作。 这些操作必须在通过膨胀从头开始创建视图如果不为空(例如在刷新时)获取现有视图。

    另一个将此解决方案应用于 ListView ArrayAdapter 的好例子出现在https://stackoverflow.com/a/3874639/978329

    【讨论】:

      猜你喜欢
      • 2019-10-06
      • 2021-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      相关资源
      最近更新 更多