可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to show the Bitmap image in ImageView from sd card which is stored already. After run my application is crash and getting OutOfMemoryError error of:
(java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM)
I have no idea or why its out of memory. I think my image size is very large so I tried to change it.
Iterator it = imageArray.iterator(); while (it.hasNext()) { Object element = it.next(); String objElement = element.toString(); Log.e("objElement ", " = " + objElement); final ImageView imageView = new ImageView (getContext()); final ProgressBar pBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmall); imageView.setTag(it); pBar.setTag(it); imageView.setImageResource(R.drawable.img_placeholder); pBar.setVisibility(View.VISIBLE); if (objElement.endsWith(mp3_Pattern)) { Log.e("Mp3 ", " ends with "); pBar.setVisibility(View.GONE); imageView.setImageResource(R.drawable.audio_control); } if (objElement.endsWith(png_Pattern)) { Bitmap bitmap = BitmapFactory.decodeFile(objElement); int size = Math.min(bitmap.getWidth(), bitmap.getHeight()); int x = (bitmap.getWidth() - size) / 2; int y = (bitmap.getHeight() - size) / 2; Bitmap bitmap_Resul = Bitmap.createBitmap(bitmap, x, y, size, size); Log.e("bitmap_Resul "," = "+ bitmap_Resul); if (bitmap_Resul != bitmap) { bitmap.recycle(); } imageView.setImageBitmap(bitmap_Resul); Log.e("png_Pattern ", " ends with "); Log.e(" bitmap "," = " + bitmap); } holder.linearLayout.addView(imageView); holder.linearLayout.addView(pBar);
The log cat information:
08-27 14:11:15.307 1857-1857/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.tazeen.classnkk, PID: 1857 java.lang.OutOfMemoryError: Failed to allocate a 23970828 byte allocation with 2097152 free bytes and 2MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.Bitmap.nativeCreate(Native Method) at android.graphics.Bitmap.createBitmap(Bitmap.java:812) at android.graphics.Bitmap.createBitmap(Bitmap.java:789) at android.graphics.Bitmap.createBitmap(Bitmap.java:709) at android.graphics.Bitmap.createBitmap(Bitmap.java:634) at com.example.tazeen.classnkk.AllPosts_Page$MyListAdapter.getView(AllPosts_Page.java:357) at android.widget.AbsListView.obtainView(AbsListView.java:2347) at android.widget.ListView.makeAndAddView(ListView.java:1864) at android.widget.ListView.fillDown(ListView.java:698) at android.widget.ListView.fillFromTop(ListView.java:759) at android.widget.ListView.layoutChildren(ListView.java:1659) at android.widget.AbsListView.onLayout(AbsListView.java:2151) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) at android.widget.FrameLayout.onLayout(FrameLayout.java:514) at android.view.View.layout(View.java:15671) at android.view.ViewGroup.layout(ViewGroup.java:5038) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:550) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5257) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
回答1:
OutOfMemoryError is the most common problem occured in android while especially dealing with bitmaps. This error is thrown by the Java Virtual Machine (JVM) when an object cannot be allocated due to lack of memory space and also, the garbage collector cannot free some space.
As mentioned by Aleksey, you can add below entities in your manifest file android:hardwareAccelerated="false"
, android:largeHeap="true"
it will work for some environment's.
you should definately read some of Androids Developer concept's, specially here:Displaying Bitmaps Efficiently
Read all 5 topics and rewrite your code again. If it still doesn't work we will be happy to see what you've done wrong with the tutorial material.
Here some of possible answers for these type of errors in SOF
Android: BitmapFactory.decodeStream() out of memory with a 400KB file with 2MB free heap
How to solve java.lang.OutOfMemoryError trouble in Android
Android : java.lang.OutOfMemoryError
java.lang.OutOfMemoryError
Solution for OutOfMemoryError: bitmap size exceeds VM budget
Edit: From the comments of @cjnash
For anyone that still had crashes after they added this line, try sticking your image into your res/drawable-xhdpi/ folder instead of your res/drawable/ and it might resolve your issue.
回答2:
have you tried adding this to your manifest under applications? android:largeHeap="true"
?
like this
回答3:
Actually you can add in your manifest these lines android:hardwareAccelerated="false"
, android:largeHeap="true"
it is working for some situations, but be aware that the other part of code can be arguing with this.
回答4:
For me, the problem was that my .png file was being de-compressed to be a really huge bitmap in memory, because the image had very large dimensions (even though the file size was tiny).
So the fix was to simply resize the image :)
回答5:
This should work
BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);
回答6:
Resize your image before setup to ImageView like this:
Bitmap.createScaledBitmap(_yourImageBitmap, _size, _size, false);
where size is actual size of ImageView. You can reach size by measuring:
imageView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
and use next size imageView.getMeasuredWidth()
and imageView.getMeasuredHeight()
for scaling
.
回答7:
Use Glide Library and Override size to less size;
Glide.with(mContext).load(imgID).asBitmap().override(1080, 600).into(mImageView);
回答8:
I got below error
"E/art: Throwing OutOfMemoryError "Failed to allocate a 47251468 byte allocation with 16777120 free bytes and 23MB until OOM"
after adding android:largeHeap="true"
in AndroidManifest.xml then I rid of all the errors
回答9:
I have resolved this problem by resizing the image to lower size. I am using xamarin form. decreasing the size of the PNG image resolved the problem.
回答10:
Soluton try this in your Manifest File and use Glide Library
compile 'com.github.bumptech.glide:glide:3.7.0'
**Use Glide Library and Override size to less size;** if (!TextUtils.isEmpty(message.getPicture())) { Glide.with(mContext).load(message.getPicture()) .thumbnail(0.5f) .crossFade() .transform(new CircleTransform(mContext)) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(holder.imgProfile); }
android:hardwareAccelerated="false"
android:largeHeap="true"
Use this library
compile 'com.github.bumptech.glide:glide:3.7.0'
Its Working Happy Coding
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Paint; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; public class CircleTransform extends BitmapTransformation { public CircleTransform(Context context) { super(context); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return circleCrop(pool, toTransform); } private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; // TODO this could be acquired from the pool too Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); return result; } @Override public String getId() { return getClass().getName(); } }
回答11:
Bitmap image =((BitmapDrawable)imageView1.getDrawable()).getBitmap(); ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG,50/100,byteArrayOutputStream);
50/100 if one uses 100 then original resolution can stopped the Apps for out of memory.
if 50 or less than 100 this will be 50% or less than 100 resolution so this will prevent from out of memory problem
回答12:
I had the problem too.
Same with most of others above. The problem is caused by huge image.
Just resize some images, and no need to change any code.
回答13:
In some cases (e.g. operations in a loop) garbage collector is slower than your code. You can use a helper method from this answer to wait for garbage collector.
回答14:
If uploading an image, try reducing the image quality, which is the second parameter of the Bitmap. This was the solution in my case. Previously it was 90, then I tried with 60 (as it is in the code below now).
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream); ByteArrayOutputStream baos = new ByteArrayOutputStream(); finalBitmap.compress(Bitmap.CompressFormat.JPEG,60,baos); byte[] b = baos.toByteArray();
回答15:
I'm a newbie in android developing but I hope my solution helps, it works on my condition perfectly. Im using Imageview and set it's background to "src" because im trying to make a frame animation. I got the same error but when I tried to code this it worked
int ImageID = this.Resources.GetIdentifier(questionPlay[index].Image.ToLower(), "anim", PackageName); imgView.SetImageResource(ImageID); AnimationDrawable animation = (AnimationDrawable)imgView.Drawable; animation.Start(); animation.Dispose();
回答16:
Try the simplest one. Maybe Your app is crashing because your image size (in MB) is too large so it is not allocating space for that. So before pasting your image in drawable just reduce the size by any viewer software or if you are taking image from gallery at the run time than before saving it compress your bitmap. It worked for me. definitely for u will be.
回答17:
I ran into this problem when I didn't kill off my old activity when moving on to a new activity. I fixed it with finish();
Intent goToMain = new Intent(this,MainActivity.class); startActivity(goToMain); finish();
回答18:
This worked for me: just move images from drawable folder to drawable-hdpi.
回答19:
Issue : Failed to allocate a 37748748 byte allocation with 16777120 free bytes and 17MB until OOM
Solution : 1.open your manifest file 2. inside application tag just add below two lines
android:hardwareAccelerated="false" android:largeHeap="true"
Example :
回答20:
I have found that images in the 'drawable' folder will get converted to a much larger image on high def phones. For example, a 200k image will be resampled to a higher res, like 800k or 32000k. I had to discover this on my own and to date have not seen documentation for this heap memory trap. To prevent this I put everything in a drawable-nodpi folder (in addition to using 'options' in BitmapFactory based on the particular device heap). I can't afford to have the size of my app bloated with multiple drawable folders, particularly as the range of screen defs is so vast now. The tricky thing is studio now doesn't specifically indicate the 'drawable-nodpi' folder as such in the project view, it just shows a 'drawable' folder. If you're not careful, when you drop an image to this folder in studio, it won't actually get dropped into the drawable-nodpi:
Careful here 'backgroundtest' did not actually go to drawable-nodpi and will be resampled higher, such as 4x or 16x of the original dimensions for high def screens.
Be sure to click down to the nodpi folder in the dialogue, as the project view won't show you all drawable folders separately like it used to, so it won't be immediately apparent that it went to wrong one. Studio recreated the vanilla 'drawable' at some point for me after I had deleted it long ago:
回答21:
You have to change the size of object in drawable. It's too big for android to display. e.g. If you are setting image try image with less pixels. It works for me. Thanks. :)