Android 画廊自定义适配器

发布于 2024-11-02 10:29:14 字数 255 浏览 7 评论 0 原文

我有一个问题,也许是一个愚蠢的问题,但我认为它很重要。

上的参数:convertView(View)

为什么public View getView(intposition,ViewconvertView,ViewGroupparent)

总是为空? android 应该在第一次创建视图后回收它们,不是吗?或者我该如何回收这些视图?

我觉得该方法接收这 3 个参数,但在谷歌示例中他们没有使用其中任何一个。

I have a question, maybe a silly one, but I think it is important.

Why the parameter: convertView (View) on the

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

is always null? android is supposed to recycle the views once they're created the first time, isn't it? or how can I do to recycle those views?

I feel like the method receives those 3 parameters, but in none of the google examples they use either of them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

溺ぐ爱和你が 2024-11-09 10:29:14

不幸的是,由于Android 错误 3376。 Gallery 不实现 View 回收(至少从 Gingerbread/2.3.4 开始)。

bug 中的评论者建议分叉 Gallery.java(来自 AOSP)并自己实现,这可能是最好的选择。

Unfortunately, convertView will always be null, due to Android bug 3376. Gallery does not implement View recycling (at least as of Gingerbread/2.3.4).

A commenter in the bug suggests forking Gallery.java (from AOSP) and implementing it yourself, which may be the best option.

苹果你个爱泡泡 2024-11-09 10:29:14

当调用此函数时,convertView 参数确实会在第一次时为 null。然后,如果您滚动列表/图库,Android 会给您相同的视图,该视图是之前使用此函数构建的,您应该使用它基于旧视图来优化构建新视图。

另外,您应该将对子视图的引用存储在某处。

为了更好地理解这一点,请查看此代码示例(取自 Android 开发者):

public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid unneccessary calls
        // to findViewById() on each row.
        ViewHolder holder;

        // When convertView is not null, we can reuse it directly, there is no need
        // to reinflate it. We only inflate a new View when the convertView supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text, null);

            // Creates a ViewHolder and store references to the two children views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }

        // Bind the data efficiently with the holder.
        holder.text.setText(DATA[position]);
        holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

        return convertView;
    }

The convertView parameter indeed will be null a few first times, when this function will be called. Then if you scroll the list / galery Android will give you the same view, which was constructed earlier using this function, and you should use it to optimally construct the new view, based on the old one.

Also, you should store the references to child view somewhere.

To better undestand that, look at this code example (taken from Android Developers):

public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid unneccessary calls
        // to findViewById() on each row.
        ViewHolder holder;

        // When convertView is not null, we can reuse it directly, there is no need
        // to reinflate it. We only inflate a new View when the convertView supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text, null);

            // Creates a ViewHolder and store references to the two children views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }

        // Bind the data efficiently with the holder.
        holder.text.setText(DATA[position]);
        holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

        return convertView;
    }
他是夢罘是命 2024-11-09 10:29:14

getView() 方法中,通常您会检查 convertView 是否为空,如果不是,您只需重写视图中的字段,使其适应您基于获得的数据位置而不是创建一个新的视图(通过通货膨胀或任何你想要的方法)。

希望有帮助,
JQ科雷亚

On getView() method normally you check if convertView is null, and if it isn't you just rewrite the fields in the View adapting it to the data you get based on the position instead of creating a new View (from inflation or whatever method you want).

Hope it helped,
JQCorreia

没企图 2024-11-09 10:29:14

getView() 有第二个参数作为 view(convertView)。这个 convertView 是从上一次迭代返回的视图。对于第一次迭代,它将为空,适配器将创建(实例)视图。当创建所需布局完成时,视图将返回给其调用者。从下一次迭代开始,该返回值将作为第二个参数可用。因此,人们可以决定重用先前返回的视图,而不是通过查看此参数来重新创建。因此,Android 实现了可重用性功能创建多个列表项时。

getView() has a second parameter as view(convertView).This convertView is the view which is returned from previous iteration.For the first iteration it will be null and adapter will create (instance) view.When it is done with creating required layout,the view will be returned to its caller.This returned value will be available as 2nd parameter from the next iteration onwards.So one can decide to reuse previously returned view instead of recreating by looking at this parameter.Thus Android achives re-usability feature while creating multiple list items.

安人多梦 2024-11-09 10:29:14

由于convertView将始终为空,因此您应该实现自己的缓存和重用项目的算法。
这是我的 Gallery 适配器的实现

public View getView(int position, View convertView, ViewGroup parent) {
    int arrPosition = position % VIEW_CHACHE_SIZE;
    ImageView imageView;
    mCursor.moveToPosition(position);
    if (parent.getHeight() > 0 && layoutParams.height == 0) {
        layoutParams = new Gallery.LayoutParams(parent.getWidth() / VISIBLE_IMAGES_COUNT, (int) (parent.getHeight() * IMAGE_HEIGHT_COEFICIENT));
        viewsList[0].setLayoutParams(layoutParams);
    }
    if (convertView != null) {
        Log.i("GALLERY", "convert view not null");
    }
    // check views cache
    if (viewsList[arrPosition] == null) {
        imageView = new ImageView(mContext);
        imageView.setPadding(3, 3, 3, 3);
        viewsList[arrPosition] = imageView;
    } else {
        imageView = viewsList[arrPosition];

        if (position == arrPosition) {
            if (imageView.getDrawable().equals(imagesList.get(position))) {
                return imageView;
            }
        }
    }
    // check images cache
    if (imagesList.get(position) != null) {
        imageView.setImageDrawable(imagesList.get(position));
    } else {
        byte[] photo = mCursor.getBlob(mCursor.getColumnIndex(DataProxy.PHOTO_COLUMN));
        imagesList.put(position, new BitmapDrawable(BitmapFactory.decodeByteArray(photo, 0, photo.length)));
        imageView.setImageDrawable(imagesList.get(position));
    }
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    imageView.setLayoutParams(layoutParams);


    return imageView;
}

      .........................................................

    private SparseArray<Drawable> imagesList = new SparseArray<Drawable>();
private ImageView[] viewsList = new ImageView[VIEW_CHACHE_SIZE];
private Gallery.LayoutParams layoutParams = new LayoutParams(0, 0);
private static final int VIEW_CHACHE_SIZE = 4;

Since convertView will always be null you should implement your own algorithm of caching and reusing items.
This is my implementation of Gallery adapter

public View getView(int position, View convertView, ViewGroup parent) {
    int arrPosition = position % VIEW_CHACHE_SIZE;
    ImageView imageView;
    mCursor.moveToPosition(position);
    if (parent.getHeight() > 0 && layoutParams.height == 0) {
        layoutParams = new Gallery.LayoutParams(parent.getWidth() / VISIBLE_IMAGES_COUNT, (int) (parent.getHeight() * IMAGE_HEIGHT_COEFICIENT));
        viewsList[0].setLayoutParams(layoutParams);
    }
    if (convertView != null) {
        Log.i("GALLERY", "convert view not null");
    }
    // check views cache
    if (viewsList[arrPosition] == null) {
        imageView = new ImageView(mContext);
        imageView.setPadding(3, 3, 3, 3);
        viewsList[arrPosition] = imageView;
    } else {
        imageView = viewsList[arrPosition];

        if (position == arrPosition) {
            if (imageView.getDrawable().equals(imagesList.get(position))) {
                return imageView;
            }
        }
    }
    // check images cache
    if (imagesList.get(position) != null) {
        imageView.setImageDrawable(imagesList.get(position));
    } else {
        byte[] photo = mCursor.getBlob(mCursor.getColumnIndex(DataProxy.PHOTO_COLUMN));
        imagesList.put(position, new BitmapDrawable(BitmapFactory.decodeByteArray(photo, 0, photo.length)));
        imageView.setImageDrawable(imagesList.get(position));
    }
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    imageView.setLayoutParams(layoutParams);


    return imageView;
}

      .........................................................

    private SparseArray<Drawable> imagesList = new SparseArray<Drawable>();
private ImageView[] viewsList = new ImageView[VIEW_CHACHE_SIZE];
private Gallery.LayoutParams layoutParams = new LayoutParams(0, 0);
private static final int VIEW_CHACHE_SIZE = 4;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文