【问题标题】:Android ListView Layout inflaterAndroid ListView 布局充气器
【发布时间】:2012-11-07 15:50:22
【问题描述】:

我们目前正在大学里处理列表视图。我的讲师给了我们一个简单的应用程序,它在列表中显示邮件消息,当用户选择一个时,它会在新活动中显示消息的内容。我几乎了解正在发生的所有事情,但是我想清除一些灰色区域!

基本上我想知道这部分代码的作用是什么?

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.inbox_row, null);
    }

此方法位于扩展 ArrayAdapter 的类中。我认为这是某种形式的回收是否正确?视图何时打开和关闭屏幕?....

非常感谢任何帮助。谢谢。

【问题讨论】:

  • youtube.com/watch?v=wDBM6wVEO70。看看链接。您的问题可能已经得到解答。
  • 如果您的列表中有三个项目,并且您的 ListView 中有三行在屏幕上的空间,则 getView() 将被调用三次,并使用一个空视图来创建这三行。您不能回收当前正在使用的行。
  • 好的,我明白了,布局充气器是否基本上将视图放在它说 v = vi.inflate(.layout.inbox_row, null) 的列表中?
  • 观看链接中的视频。这应该可以帮助您更好地理解列表视图。

标签: android listview android-arrayadapter layout-inflater


【解决方案1】:

正是你所说的,一种回收的形式。

扩充布局会占用大量内存和时间,因此为了提高效率,系统会将刚刚离开屏幕的内容传递给您,您可以简单地更新其文本和图像并将它们返回给 UI .

因此,例如,如果您的列表视图在其列表中显示 6 个项目(由于其高度),它只会膨胀 6 个项目,并且在滚动期间它只会不断回收它们。

您应该使用一些额外的优化技巧,我相信评论者发布的视频链接会解释它们。

编辑

该示例是 Store 项目的 ArrayAdapter,但您可以根据需要进行设置。 适配器在 UI 和数据之间做匹配和分离层。

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null)
    convertView = newView();

    // Store is the type of this ArrayAdapter
    Store store = getItem(position);
    Holder h = (Holder) convertView.getTag();

    // And here I get the data and address them to the UI
    // as you can see, if the convertView is not null,
    // I'm not creating a new one, I'm just changing text, images, etc
    h.storeName.setText(store.getStoreName());
    h.address.setText(store.getAddressLine1());
    h.postcode.setText(store.getPostCode());
    h.distance.setText(store.getDistance());

    return convertView;
}

// I like to separate in a different method when the convertView is null
// but that's me being organisation obsessive
// but it also makes easy to see which methods are only being called the 1st time
private View newView() {
    LayoutInflater inf = LayoutInflater.from(getContext());
    View v = inf.inflate(R.layout.map_result_list, null);
    Holder h = new Holder();
    // here we store that holder inside the view itself
    v.setTag(h);

    // and only call those findById on this first start
    h.storeName = (TextView) v.findViewById(R.id.txtLine1);
    h.address = (TextView) v.findViewById(R.id.txtLine2);
    h.postcode = (TextView) v.findViewById(R.id.txtLine3);
    h.distance = (TextView) v.findViewById(R.id.txtDistance);

    return v;
}

// this class is here just to hold reference to the UI elements
// findViewById is a lengthy operation so this is one of the optimisations
private class Holder {
    TextView storeName;
    TextView address;
    TextView postcode;
    TextView distance;
}

【讨论】:

  • 我明白你的意思。但是当它被调用 6 次并且 v 不再 == null 时会发生什么?还是在幕后进行更多操作,监听屏幕上的视图并通过将 v 设置为 == 为空来释放 v?
  • 不不...我建议您观看该人评论的视频并给我一点时间,我将使用完整正确的 ArrayAdapter 实现的示例代码更新我的答案
  • 正如您在示例中看到的,返回的 v 与您之前膨胀的完全相同,然后在您的代码中,您只需将其重新用作另一个位置的视图。