ViewPager引发内存溢出错误

3

我已经实现了一个ViewPager,在使用它时出现了内存不足的错误,但我无法弄清楚原因。我有大约11个要显示的图像,每个图像的大小约为500 KB(磁盘上的大小),它们是.jpg格式。

这是代码:

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bmw_gallery);

ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
}

private class ImagePagerAdapter extends PagerAdapter {
private int[] mImages = new int[] {
    R.drawable.bmw_1series_3door_wallpaper_01,
    R.drawable.bmw_1series_3door_wallpaper_02,
    R.drawable.bmw_1series_3door_wallpaper_03,
    R.drawable.bmw_1series_3door_wallpaper_04,
    R.drawable.bmw_1series_3door_wallpaper_05,
    R.drawable.bmw_1series_3door_wallpaper_06,
    R.drawable.bmw_1series_3door_wallpaper_07,
    R.drawable.bmw_1series_3door_wallpaper_08,
    R.drawable.bmw_1series_3door_wallpaper_09,
    R.drawable.bmw_1series_3door_wallpaper_11,
    R.drawable.bmw_1series_3door_wallpaper_12
};

@Override
public int getCount() {
  return mImages.length;
}

@Override
public boolean isViewFromObject(View view, Object object) {
  return view == ((ImageView) object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
  Context context = MainActivity.this;
  ImageView imageView = new ImageView(context);
  imageView.setAdjustViewBounds(true);

  imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

  imageView.setImageResource(mImages[position]);
  ((ViewPager) container).addView(imageView, 0);
  return imageView;
}


@Override
public void destroyItem(View collection, int position, Object o) {
    View view = (View)o;
    ((ViewPager) collection).removeView(view);
    view = null;
}


}



}

我做错了什么或者我的代码缺少了什么?该怎么办?

“500kb” 是指磁盘上的大小还是 RAM 中解码后的大小? - CommonsWare
关于磁盘上的大小 - Catalin H
3个回答

10
硬盘上的一个500KB的JPEG图像会占用比这个更多的堆空间。
例如,我有一张数字照片,大小为494KB,分辨率为1455 x 1029。如果我将其加载到Android应用程序中,它将消耗1455x1029x3 = 4.3MB的堆空间。如果您有11张类似特征的图片,它们将消耗>40MB。大多数设备每个进程有16-32MB的堆空间。
如果您想要发布11个可绘制资源(在这种情况下,可能是会让您被宝马起诉的图像),则需要使用更小的图像。

不用担心被宝马起诉,因为这个应用程序不会在MarketPlace上发布,只是我自己的一个项目。 - Catalin H
那么使它使用更少资源并且不出现错误的唯一机会就是修改磁盘上它们的大小? - Catalin H
假设您想使用可绘制资源,那么是的。更准确地说,您需要低分辨率图像。问题在于,据我所知,您无法从内存中删除资源。如果这些图像是文件系统上的文件,并且您自己使用BitmapFactory加载它们,则可能有更多选项来尝试确保位图内存得到重用(请参阅BitmapFactory.Options上的inBitmap),在这种情况下,您将更好地控制内存消耗。但是,这会使应用程序变得更加复杂。 - CommonsWare
请问您能否为我提供一个示例,该示例可以从内部/外部/网络资源加载图像,并且不会占用太多的内存? - Catalin H
1
@CatalinH:你可以使用开源图像缓存,这些缓存可以通过网络搜索轻松获得。此外,在Android开发者文档中也有关于此主题的覆盖范围:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html - CommonsWare

4

你能分享一个没有使用片段的例子吗?只是一个简单的ViewPager,附上你使用的代码就可以了吗? - Amit Hooda

2
我在使用viewpager显示高分辨率图片时遇到了相同的问题。我已经搜索并尝试了http://developer.android.com/training/displaying-bitmaps/index.html中提供的所有android位图解决方案以及链接中的缓存机制,但它们都没有起作用。没有任何正确的解决方案。
然后我发现问题是:我不能正确地使用drawable文件夹结构。我将高分辨率图像保存在mdpi和hdpi文件夹中,这会导致android将图像放大到超大尺寸。100 kb的图像会导致内存增加20 mb,感谢android monitor / memory部分。所以我将这些超高分辨率图像添加到xxhdpi文件夹中,然后问题就突然解决了。然后我的图像滑块可以无缝地使用高分辨率图像。

1
@kksal55 谢谢我的朋友。我还没有看到任何缺点。 - smoothumut

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