这是我的代码:
int[] image = {R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2,
R.drawable.image1, R.drawable.image2, R.drawable.image1, R.drawable.image2};
getView:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
imageView.setBackgroundResource(image[position]);
return convertView;
}
一切都很好。没有OOM。
然后,我想首先对drawable进行采样:
public static Bitmap sampleImage(Context context, int resourceId, int sampleSize) {
Bitmap resizeBmp = null;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = sampleSize;
resizeBmp = BitmapFactory.decodeResource(context.getResources(), resourceId, opts);
return resizeBmp;
}
新的getView:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
Bitmap item = BitmapUtil.sampleMaskInShelf(getApplicationContext(), image[position], 4);
imageView.setImageBitmap(item);
// imageView.setBackgroundResource(image[position]);
return convertView;
}
事情发生了。首先,应用程序不会崩溃。但是我使用的内存超过50MB,在我向上和向下滚动后,它会导致OOM。
问题是: 1)为什么采样图像会增加使用的内存。 2)如何减少使用的内存,还有其他方法吗?
答案 0 :(得分:5)
您好像在使用ListView吗?
在这种情况下,您可以通过以下几个步骤获得更好的服务(并希望节省大量内存):
convertView
。关于如何做到这一点,已经写了很多文章。 Here is one。image1
和image2
)。每次调用getView()
时,您似乎都在对位图进行采样。您可能应该预先计算两个采样位图,然后一遍又一遍地使用它们。答案 1 :(得分:2)
有三篇优秀的Android培训文章涵盖了这个问题:
我可能会尝试阅读所有这三种技术,了解他们使用的技术并下载sample application,它将所有训练代码封装到一个示例中。我认为在您的情况下,将图像预先采样到显示尺寸然后使用LruCache可能就足够了。
答案 2 :(得分:0)
垃圾收集器不会自动为您处理位图释放,因此每当您将位图直接分配给变量时,您还需要在完成后调用bitmap.recycle()。如果不这样做会导致内存泄漏,这就是你所拥有的。但是,如果您将位图分配给drawable然后调用bitmap.recycle(),然后尝试使用drawable,您将获得异常,因为drawable无法访问回收的位图。
我正在写一个类似于你所拥有的ListView,我最终做的是在当前视口上方十多个插槽的任何位图上调用bitmap.recycle,在该ListView项上设置一个标志来显示它的位图已经被回收,然后让用户在那里向后滚动时重新加载位图。
答案 3 :(得分:0)
您不应每次都创建新视图,而应尝试重用视图,如..
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null) {
v=LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
imageView.setBackgroundResource(image[position]);
return v;
}
要在OOM上进行更多操作,您应该在以下链接上进行操作.. http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
或者您可以使用UniversalImage Loader Library加载图像..您可以从中找到它的库 UniversalImageLoader
希望这有帮助...