Android:如何在没有内存不足错误的活动中加载多个图片和声音

时间:2015-08-12 15:29:40

标签: java android android-memory

所以我的活动是高清图像的网格视图,缩小到大约64x64像素的盒子。我希望能够获取图像,然后将它们加载到活动中,但是我收到一条错误消息,指出加载所有图片所需的内存比模拟器/手机可以处理的要高很多。

我通过进入photoshop和制作64x64图像解决了这个问题,但我看到了运行视频的应用程序,并且在当前活动的视图中有数百个图像。他们如何使用一个列表视图中的所有内存进行编译?

我有另一个应用程序,它是一个播放带有20张图片的全屏动画的动画 - 但它在Android Studio中具有相同的内存绑定错误。

如何在单个活动中加载20张图片而不会出现内存不足错误。

使用GridView的活动代码       @覆盖       protected void onCreate(Bundle savedInstanceState){         super.onCreate(savedInstanceState);         的setContentView(R.layout.wallpapers);

    //**
    //Gridview, onclick of icon will open up dialog
    //allows to SAVE, SET, CANCEL - not in that order

    GridView gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(new ImageAdapter(this));

    gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v,
                                int position, long id) {
            Toast.makeText(Wallpaper.this, "Setting BG to ..." + position,
                    Toast.LENGTH_SHORT).show();
        }
    });
}

ImageAdapter代码

public class ImageAdapter extends BaseAdapter {
private Context mContext;

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

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

public Object getItem(int position) {
    return null;
}

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

// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;
    if (convertView == null) {
        // if it's not recycled, initialize some attributes
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, 8, 8, 8);
    } else {
        imageView = (ImageView) convertView;
    }

    imageView.setImageResource(mThumbIds[position]);
    return imageView;
}

// references to our images
private Integer[] mThumbIds = {
        R.raw.es_1_pix,  R.raw.es1_c, R.raw.es2_c, R.raw.es_1_pix
            //.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix,R.raw.es_1_pix
        //R.raw.es2_c, R.raw.es3_c, R.raw.es4_c,
        //R.raw.es5_c, R.raw.es6_c, R.raw.es7_c
};
}

3 个答案:

答案 0 :(得分:3)

不确定声音,但我知道图片需要使用inJustDecodeBounds=true的样本尺寸。

public int calculateInSampleSize(BitmapFactory.Options options) {

        DisplayMetrics displayMetrics = cxt.getResources().getDisplayMetrics();
        int reqWidth = displayMetrics.widthPixels;

        final int height = options.outHeight;
        final int width = options.outWidth;

        double devCal2 =  (height*1000)/width;
        int reqHeight = (int) ((devCal2/1000)*reqWidth);

        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public Bitmap createBitmap(){

        BitmapFactory.Options options2 = new BitmapFactory.Options();
        options2.inJustDecodeBounds = true;
        options2.inDither=true;
        BitmapFactory.decodeFile(cxt.getExternalFilesDir(filepath) +"/companylogo.png",options2);
        options2.inSampleSize = calculateInSampleSize(options2);//=32
        options2.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(cxt.getExternalFilesDir(filepath) +"/companylogo.png",options2);
    }

如需参考,请查看http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

答案 1 :(得分:1)

有几件事需要考虑。

  1. 更简单的解决方案 - 使用图像管理库,其中有很多。所有这些都做了以下事情:
  2. 在任何地方使用WeakReference<Bitmap>而不是位图。 WeakReference意味着当内存不足时,System可以从内存中清除图像。

    如果显示20个64 * 64图像,而不是确保不在内存中存储20个1024 * 1024图像,请在运行时或应用程序外部将其大小调整为64 * 64。

    一般来说,android可以轻松处理20个平均大小的图像(显然不是很大的图像)。如果它发生了冲突,那么代码就会出现问题。

    代码发布后

    更新:资源文件中的图像很大,缩小,你应该没问题。

答案 2 :(得分:0)

如果你真的需要全高清图像,你可以计算出你需要多少空间,并将它们逐个加载到视图中,用占位符图像替换其他视图。然后在加载一个图像后,确保系统从内存中清除该图像。但是,就像大多数人都说的那样,如果只有20张图像崩溃,那可能就是别的了。