ImageAdapter中的OOM异常

时间:2015-06-18 09:03:53

标签: java android

LogCat给了我这个错误:

Throwing OutOfMemoryError "Failed to allocate a 7485708 byte allocation with 2097152 free bytes and 5MB until OOM"
--- decoder->decode returned false
Shutting down VM
FATAL EXCEPTION: main
Process: de.holg.memory, PID: 2104
java.lang.OutOfMemoryError: Failed to allocate a 7485708 byte allocation with 2097152 free bytes and 5MB until OOM

我在阵列中添加了6张图片但是当我添加" pic_1" 6次没有错误发生。全都是~200kb。 OnClick后,图片显示在我的GridView中。有时我可以点击3次...有时只能点击一次。在我的手机上,我可以更频繁地点击。

private 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,
    };

我的ImageAdapter类:

public class ImageAdapter extends BaseAdapter {

    private Context mContext;
    private Integer[] pieces;
    private List<ImageView> imageViewsList;
    private int piece_up = -1;

    public ImageAdapter(Context c) {
        mContext = c;
        List<Integer> ipieces = new ArrayList<Integer>();
        for(int i=0; i<6; i++) {
            ipieces.add(i);
            ipieces.add(i);
        }
        Collections.shuffle(ipieces);
        pieces = (Integer[]) ipieces.toArray(new Integer[0]);
        createImageViews();
    }

    private void createImageViews() {

        imageViewsList = new ArrayList<ImageView>();
        for(int position = 0; position < getCount(); position++) {
            ImageView imageView;

            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
            imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            imageView.setPadding(8, 8, 8, 8);

            imageView.setImageResource(R.drawable.card_back);
            imageViewsList.add(imageView);

            installClick(position);
        }
    }

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

    public Object getItem(int position) {
        return imageViewsList.get(position);
    }

    public long getItemId(int position) {
        return pieces[position].longValue();
    }

    // create a new ImageView for each item referenced by the Adapter
    public synchronized View getView(int position, View convertView, ViewGroup parent) {
        return (ImageView) imageViewsList.get(position);
    }

    public void installClick(int position) {
        // final int pos = position;
        final ImageAdapter self = this;
        Log.d("ImageAdapter", "click *" + Integer.toString(position));
        ImageView imageView =(ImageView)  imageViewsList.get(position);
        imageView.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int pos = imageViewsList.indexOf((ImageView) v);
                Log.d("ImageAdapter", "click!" + Integer.toString(pos));
                show(pos);


                //UI update
                if (piece_up == -1 || piece_up == pos) {
                    // first click
                    piece_up = pos;
                } else {
                    // second click
                    if (pieces[pos] == pieces[piece_up]) {
                        // ok, it's equal
                        Toast.makeText(mContext, "good!", Toast.LENGTH_SHORT).show();
                        //
                        // remove click handler
                        removeClick(pos);
                        removeClick(piece_up);

                    } else {
                        //try again;
                         int aux[] = {piece_up, pos};
                         SleepHide update = new SleepHide(mContext, self, aux);
                         Handler mHandler = new Handler();
                         mHandler.postDelayed(update, 1500);
                    }

                    piece_up = -1;
                }

            }
        });
    }

    public void removeClick(int position) {
        ImageView aux;
        aux = (ImageView) imageViewsList.get(position);
        aux.setOnClickListener(null);
    }

    public void hide(int position) {
        ImageView img;
        img = (ImageView) imageViewsList.get(position);
        //int piece = pieces[position];
        img.setImageResource(R.drawable.card_back);
    }

    public void show(int position) {
        ImageView img;
        img = (ImageView) imageViewsList.get(position);
        int piece = pieces[position];
        img.setImageResource(mThumbIds[piece]);

    }
    //
    // references to our images
    private 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,
        };
}
class SleepHide implements Runnable {
    //private Context context;
    private int[] positions;
    private ImageAdapter adapter;

    public SleepHide(Context c, ImageAdapter b, int[] pos) {
        //context = c;
        adapter = b;
        positions = pos;

        Log.d("SleepHide", "click!");
        adapter.removeClick(pos[0]);
        adapter.removeClick(pos[1]);
    }

    public void run() {
        Log.d("SleepHide", "run!");
        adapter.hide(positions[0]);
        adapter.hide(positions[1]);
        adapter.installClick(positions[0]);
        adapter.installClick(positions[1]);
    }

}

2 个答案:

答案 0 :(得分:0)

您可以将此行添加到清单文件中的应用程序类声明中,以请求更大的堆大小。

android:largeHeap="true" 

AndroidManifest.xml中的应用程序类声明

<application
            android:label="@string/app_name"
            android:allowBackup="true"
            android:icon="@drawable/title_image"
            android:largeHeap="true">
</application>

这将完全消除您的OOM崩溃!!

答案 1 :(得分:0)

应用程序已超出堆大小。所以你必须解码图像,使其落入堆大小。在适配器中执行此代码

您可以在适配器中更改show()方法。

public void show(int position) {
ImageView img;
img = (ImageView) imageViewsList.get(position);
int piece = pieces[position];
BitmapFactory.Options options = new BitmapFactory.Options();
    options.inDither = false;
    options.inJustDecodeBounds = false;
    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
    options.inSampleSize = 3;
    options.inPurgeable = true;

    Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
            mThumbIds[piece],options);
img.setImageBitmap(icon);

}

尝试一次。