I understand that this question is asked few times. None of them is clear on the solution. Let me explain the problem.
- I have an Activity which loads 4 images at a time.
- I load the images in the onResume() method.
- The Activity throws bitmap error when loading.
Notes.
- I am setting image using setImageResource(R.drawable.xxxx) method call and not bitmap/drawables directly.
- The images are scaled correctly.
- The activtiy WORKS FINE in all emulators prior to 2.3 and is WORKING FINE in Actual device (Samsung Galaxy 5)
- The error is appearing on first initialisation and no orientation change event is fired.
- images are 800 x 600 in scale and averages 15kb(each) in size.
Let me know any solutions. Also let me know if you have similar issues with Android 2.3.3 emulator.
[update] -snippets
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
img_topLeft = (ImageView) findViewById(R.id.Img_Alph_Q_TopLeft);
img_topRight = (ImageView) findViewById(R.id.Img_Alph_Q_TopRight);
img_bottomLeft = (ImageView) findViewById(R.id.Img_Alph_Q_BottomLeft);
img_bottomRight = (ImageView) findViewById(R.id.Img_Alph_Q_BottomRight);
...
}
protected void onResume() {
super.onResume();
img_topLeft.setImageResource(R.drawable.xxx);
img_topRight.setImageResource(R.drawable.xxx);
img_bottomLeft.setImageResource(R.drawable.xxx);
img_bottomRight.setImageResource(R.drawable.xxx);
...
}
03-21 08:59:17.362: ERROR/dalvikvm-heap(5883): 4320000-byte external allocation too large for this process. 03-21 08:59:17.412: ERROR/GraphicsJNI(5883): VM won't let us allocate 4320000 bytes 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): FATAL EXCEPTION: main 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.nativeCreate(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:477) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createBitmap(Bitmap.java:444) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:349) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:498) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:473) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.loadDrawable(Resources.ja开发者_如何学Gova:1709) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.content.res.Resources.getDrawable(Resources.java:581) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.resolveUri(ImageView.java:501) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.widget.ImageView.setImageResource(ImageView.java:280) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at Quiz.java:124) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): Quiz.onResume(Quiz.java:92) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.Activity.performResume(Activity.java:3832) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.access$1500(ActivityThread.java:117) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Handler.dispatchMessage(Handler.java:99) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.os.Looper.loop(Looper.java:123) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at android.app.ActivityThread.main(ActivityThread.java:3683) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invokeNative(Native Method) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at java.lang.reflect.Method.invoke(Method.java:507) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 03-21 08:59:17.432: ERROR/AndroidRuntime(5883): at dalvik.system.NativeStart.main(Native Method)
Thanks. Managed to resolve it. Sharing the code for benefit of others Custom class that resolved this issue. based on @Janardhanan.S link.
public class BitmapResizer {
public static Bitmap decodeImage(Resources res, int id ,int requiredSize){
try {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, id, o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=requiredSize;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeResource(res, id, o2);
} catch (Exception e) {
}
return null;
}
}
//Class call
int requiredsize = 100; // Still playing around with this number to find the optimum value
img_topLeft.setImageBitmap(BitmapResizer.decodeImage(getResources(),
AlphResourceSet.R.drawable.xxx, requiredsize));
Bitmap consumes a lot of memory space. dont create a new bitmap variable for all image you load on activity, instead you can create one bitmap variable and reuse them as much as you can.
you can use this snippet to resize bitmap
http://pastebin.com/D8vbQd2u
Can you post a code snippet of the Activity + stacktrace.
Did you already check the Avoiding memory leaks article ?
Especially the following part :
When a Drawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)
It seems the images are very heavy in nature. I recommend to start the AsyncTimer which actually returns the bitmap instance and in the doBackground() of the AsyncTask pass the image id and rescale it to desire size say 32 x 32 using createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
method of the Bitmap class.
精彩评论