9

我有一个关于在自定义数组适配器的 getView 方法中回收视图的不清楚的问题。

我知道元素被重用了,但是我怎么知道在 if 语句的第一部分中要实现什么,以及在第二部分中实现什么?

现在我有以下代码。我之所以提出这个问题,是因为在语句的第二部分中删除了代码,这导致了前 9 个元素的列表,这些元素被重复多次而不是所有元素。我真的不知道究竟是什么原因造成的......

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

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);

            title = getItem(position).getTitle();
            size = calculateFileSize(position);

            txtTitle = (TextView) row.findViewById(R.id.txtTitle);
            tvFileSize = (TextView) row.findViewById(R.id.tvFileSize);

            txtTitle.setText(title);
            tvFileSize.setText(size);

        } else {

            title = getItem(position).getTitle();
            size = calculateFileSize(position);

            txtTitle = (TextView) row.findViewById(R.id.txtTitle);
            tvFileSize = (TextView) row.findViewById(R.id.tvFileSize);

            txtTitle.setText(title);
            tvFileSize.setText(size);
        }

        return row;
    } 
4

5 回答 5

14

这很简单。第一次没有创建行,所以你必须给它们充气。之后,Android 操作系统可能会决定回收您已经膨胀且不再可见的视图。这些已经膨胀并传递到 convertView 参数中,因此您所要做的就是安排它以显示新的当前项目,例如将正确的值放入各种文本字段中。

在此处输入图像描述

简而言之,在第一部分中,您应该执行膨胀并填充值,在第二部分中,如果(if convertView != null)您应该只覆盖该字段,因为鉴于视图已被回收,文本视图包含旧项目的值。

这篇文章是很好的起点

于 2013-04-09T21:41:20.103 回答
13

我知道元素被重用了,但是我怎么知道在 if 语句的第一部分中要实现什么,以及在第二部分中实现什么?

一旦你掌握了它的窍门,这个组织就非常简单:

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

    if (convertView == null) {
        /* This is where you initialize new rows, by:
         *  - Inflating the layout,
         *  - Instantiating the ViewHolder,
         *  - And defining any characteristics that are consistent for every row */
    } else {
        /* Fetch data already in the row layout, 
         *    primarily you only use this to get a copy of the ViewHolder */
    }

    /* Set the data that changes in each row, like `title` and `size`
     *    This is where you give rows there unique values. */

    return convertView;
}

有关 ListView 的 RecycleBin 的工作原理以及 ViewHolders 为何如此重要的详细说明,请观看Turbo Charge your UI,由 Android 的主要 ListView 程序员提供的 Google I/O 演示。

于 2013-04-09T21:43:07.287 回答
5

你想ViewHolder在你的MainActivity. 就像是

 static class ViewHolder
    {
        TextView tv1;
        TextView tv2;
    }

然后在你的getView,你第一次Views从你的 xml 中获取你的if并在之后重用它们else

View rowView = convertView;
        if (rowView == null)
        {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(R.layout.layout_name_to_inflate, parent, false);
            holder = new ViewHolder();
            holder.tv1= (TextView) rowView.findViewById(R.id.textView1);
            holder.tv2 = (RadioGroup) rowView.findViewById(R.id.textView2);             
            rowView.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) rowView.getTag();
        }
于 2013-04-09T21:47:07.690 回答
4

我建议您使用 View holder 和 convertview 模式来创建您的 listView,因为它会更有效。是一个很好的解释它如何与重用策略一起工作。这将回答您关于回收如何工作的问题。如果您想参考代码示例,我在GitHub 上有。

希望这可以帮助。

于 2013-04-09T21:43:22.130 回答
1

如果没有效果图,我真的无法理解问题的最后一部分,但对于第一部分“在 if 语句的第一部分中实现什么,以及在第二部分中实现什么”我想我已经找到了这个实现非常普遍。

您将首先找到视图引用并将它们存储到静态类ViewHolder,然后将其附加到新膨胀视图的标签上。当 listview 回收视图并convertView传递a 时,getView您可以从convertView's 标记中获取 ViewHolder,因此您不必再次查找引用(这大大提高了性能)并使用给定位置的对象更新视图数据.

从技术上讲,您并不关心视图的位置,因为您关心的只是对需要更新的视图的引用,这些视图保存在它的 ViewHolder 中。

@Override
public View getView(int position, View convertView, ViewGroup container) {
    ViewHolder holder;
    Store store = getItem(position);
    if (convertView == null) {
        convertView = mLayoutInflater.inflate(R.layout.item_store, null);

        // create a holder to store references
        holder = new ViewHolder();

        // find references and store in holder
        ViewGroup logoPhoneLayout = (ViewGroup) convertView
                .findViewById(R.id.logophonelayout);
        ViewGroup addressLayout = (ViewGroup) convertView
                .findViewById(R.id.addresslayout);

        holder.image = (ImageView) logoPhoneLayout
                .findViewById(R.id.image1);
        holder.phone = (TextView) logoPhoneLayout
                .findViewById(R.id.textview1);
        holder.address = (TextView) addressLayout
                .findViewById(R.id.textview1);

        // store holder in views tag
        convertView.setTag(holder);
    } else {

        // Retrieve holder from view
        holder = (ViewHolder) convertView.getTag();
    }

    // fill in view with our store (at this position)
    holder.phone.setText(store.phone);
    holder.address.setText(store.getFullAddress());

    UrlImageViewHelper.setUrlDrawable(holder.image, store.storeLogoURL,
            R.drawable.no_image);

    return convertView;
}

private static class ViewHolder {
    ImageView image;
    TextView phone;
    TextView address;
}
于 2013-04-09T21:46:28.343 回答