安卓相册自定义适配器

4
我有一个问题,可能有点傻,但我认为它很重要。
为什么在以下方法中参数convertView(View)始终为空? public View getView(int position, View convertView, ViewGroup parent)
Android应该在视图第一次创建后回收它们,不是吗?或者我该如何回收这些视图呢?
我感觉这个方法接收了这3个参数,但在谷歌的例子中,他们都没有使用其中任何一个。
5个回答

9

很不幸,由于Android bug 3376的存在,convertView将始终为null。Gallery没有实现视图回收(至少在Gingerbread/2.3.4版本中没有)。

一个评论者建议从AOSP中派生Gallery.java并自行实现,这可能是最好的选择。


1
DroidUX GalleryFlow已经实现了解决上述错误的工作。使用GalleryFlow小部件,当缓存中有可回收视图时,convertview将不会为空,就像在ListView中发生的那样。您可以使用GalleryFlow作为股票库的替代品。在这里查看:http://www.droidux.com - Ricky Lee

0

convertView 参数在此函数被调用的前几次确实会是 null。然后,如果您滚动列表/画廊,Android 将为您提供相同的视图,该视图是使用此函数之前构建的视图,并且您应该使用它来基于旧视图最优地构建新视图。

此外,您应该将子视图的引用存储在某个地方。

为了更好地理解这一点,请查看以下代码示例(取自 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;
    }

嗨Kocus,感谢你的回答。看起来很清楚,但问题是无论我在画廊中滚动或快速滑动多少次,我始终得到convertView == null,我也像示例建议的那样使用了视图持有者。这是否是预期行为? - lblasa
@Iblasa - 是的,你说得对。我特意在我的旧代码中使用了Gallery,并且似乎Gallery通过其适配器永远不会重用旧视图... - Kocus

0

由于convertView始终为null,您应该实现自己的缓存和重用项目的算法。 这是我实现的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;

@user1719863 看看这个例子:http://www.edumobile.org/android/android-development/image-gallery-example-in-android/ - Roman Nazarevych

0
通常在getView()方法中,您会检查convertView是否为空,如果不为空,则只需重写View中的字段,根据position获取的数据来适应它,而不是创建一个新的View(从膨胀或任何您想要的方法)。
希望这有所帮助, JQCorreia

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接