关于android:使用自定义GridView的Out of Memory异常

Out Of Memory Exception with custom GridView

本问题已经有最佳答案,请猛点这里访问。

我有一个自定义网格视图的代码,每次我尝试运行它时,它会因OutOfMemoryException而崩溃。 我想解决方案是调整阵列中的图像大小......

主要活动代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class AndroidGridLayoutActivity extends Activity {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.grid_layout);

            GridView gridView = (GridView) findViewById(R.id.grid_view);

            // Instance of ImageAdapter Class
            gridView.setAdapter(new ImageAdapter(this));

            /**
             * On Click event for Single Gridview Item
             * */
            gridView.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView< ? > parent, View v,
                        int position, long id) {

                    // Sending image id to FullScreenActivity
                    Intent i = new Intent(getApplicationContext(), FullImageActivity.class);
                    // passing array index
                    i.putExtra("id", position);
                    startActivity(i);
                }
            });
        }



}

图像适配器代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    // Keep all Images in array
    public Integer[] mThumbIds = {
            R.drawable.pic_1, R.drawable.pic_2,
            R.drawable.pic_3, R.drawable.pic_4,
            R.drawable.pic_5, R.drawable.pic_6,
            R.drawable.pic_7, R.drawable.pic_8,
            R.drawable.pic_9, R.drawable.pic_10,
            R.drawable.pic_11, R.drawable.pic_12,
            R.drawable.pic_13, R.drawable.pic_14,
            R.drawable.pic_15
    };

    // Constructor
    public ImageAdapter(Context c){
        mContext = c;
    }

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

    @Override
    public Object getItem(int position) {
        return mThumbIds[position];
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {        
        ImageView imageView = new ImageView(mContext);
        imageView.setImageResource(mThumbIds[position]);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setLayoutParams(new GridView.LayoutParams(70, 70));

        return imageView;
    }
}

全屏代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class FullImageActivity extends Activity {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.full_image);

        // get intent data
        Intent i = getIntent();

        // Selected image id
        int position = i.getExtras().getInt("id");
        ImageAdapter imageAdapter = new ImageAdapter(this);

        ImageView imageView = (ImageView) findViewById(R.id.full_image_view);
        imageView.setImageResource(imageAdapter.mThumbIds[position]);
    }

}

有什么建议吗?


您正在尝试为图像数据分配太多内存。正如您在评论中所解释的那样,您的图像非常大,一旦创建适配器,它们就会被读取。

将其读入内存将消耗每个像素4个字节,因此如果您的图像是1024像素的正方形,则数学运算为:

  • 1024×1024×4 = 4MB
  • 15张图像×4 MB /图像= 60MB

这可能超过48MB的堆预算。

您可能希望提高显示这些图像的效率。考虑:

  • 仅在显示时加载图像,使用GridView的getView()机制;
  • 使用BitmapFactory加载具有样本大小的位图。

  • Esp表示"..在GridView中加载图像:
    您可以使用inSampleSize加载所有图像并用原始图像替换可见图像 - 这对于可见的视图部分是有意义的,动态加载图像而不包含BitmapFactoryBitmapFactory及其Options

    您可以根据不同的设备缩小它们以加载图像而不会遇到内存问题。
    在您的情况下,某些手机在首次运行时可能不会表现出相同的行为,但最终,如果不处理优化的图像加载解决方案,应用程序将崩溃。

    将缩小版本加载到内存中的主题。
    http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
    Android上的内存不足错误

    关于如何避免它们:
    如何在Android中使用位图时避免内存不足错误

    概述:

    Android Out of Memory Error: Causes, Solution and Best practices


    http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html

    在将drawable设置为imageview的背景之前,即:

    1
    iv.setBackgroundResource(R.drawable.image);

    获取缩放位图或尝试其他选项,如inSampleSize,请检查您的解决方案如何影响图像质量。

    评论:

    1
    2
    3
    Bitmap drawableImage=BitmapFactory.decodeResource(context.getResources(),R.drawable.image);
    Bitmap bitmap = Bitmap.createScaledBitmap(drawableImage, width, height, false);
    Drawable drawableScaled = new BitmapDrawable(context.getResources(), bitmap);