0

对于我正在开发的应用程序,我正在尝试使用大量图像填充 GridView。为了避免 OutOfMemoryExceptions,我检查了可用内存量,当达到某个阈值时,我尝试像这样释放内存:

private void freeUpMemory() {
    // Clear ImageViews up to current position
    for (int i = 0; i < mCurrentPosition; i++) {
        RelativeLayout gridViewElement = (RelativeLayout) mGridView.getChildAt(i);
        if (gridViewElement != null) {
            ImageView imageView = (ImageView) gridViewElement.findViewById(R.id.image);
            imageView.getDrawable().setCallback(null);
            imageView = null;
        }
    }
}

我注意到这实际上并没有释放内存。我不知道是为什么。我错过了什么吗?

4

2 回答 2

3

当您的 ImageAdapter 获得 convertView 不为空的“getView()”回调时,它告诉您以前由 ImageAdapter 提供的此视图不再在屏幕上可见。这是恢复视图使用的资源的好时机。类似于以下内容:

 ImageView iv = (ImageView)convertView.findViewById(R.id.image_view_in_grid_item);
 iv.setDrawable(null);

应该删除对存储在 ImageView 中的 Drawable 的引用。如果您的代码中没有其他对该 Drawable 的引用,则它应该可用于垃圾回收。

更好的是,如果您要显示另一个图像。

iv.setDrawable(newImage);

然后将 convertView 作为网格使用的新视图返回,将用新的 Drawable 替换旧的 Drawable,删除引用并可能对图像进行垃圾收集。

于 2013-08-05T18:05:08.567 回答
0

你应该看看 Android 的 BitmapFactory.Options 类。它在位图上提供了许多控件,其中两个在处理大量图像时非常有趣。

我认为最好的解决方案是将inSampleSize设置为 2 或 4 之类的值。这会降低图像质量,但会节省大量内存。尝试不同的值,直到找到一个好的比率。

来自 Android 文档 ( http://developer.android.com/training/displaying-bitmaps/load-bitmap.html ) 的示例:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

还有inPurgeable,允许系统使用现有位图的空间,但您必须小心,因为它可能导致崩溃或无效位图。

于 2013-08-05T16:05:30.370 回答