标签云

微信群

扫码加入我们

WeChat QR Code

I have a list view with a couple of image buttons on each row. When you click the list row, it launches a new activity. I have had to build my own tabs because of an issue with the camera layout. The activity that gets launched for the result is a map. If I click on my button to launch the image preview (load an image off the SD card) the application returns from the activity back to the listview activity to the result handler to relaunch my new activity which is nothing more than an image widget. The image preview on the list view is being done with the cursor and ListAdapter. This makes it pretty simple, but I am not sure how I can put a resized image (I.e. Smaller bit size not pixel as the src for the image button on the fly. So I just resized the image that came off the phone camera.The issue is that I get an out of memory error when it tries to go back and re-launch the 2nd activity.Is there a way I can build the list adapter easily row by row, where I can resize on the fly (bit wise)? This would be preferable as I also need to make some changes to the properties of the widgets/elements in each row as I am unable to select a row with the touch screen because of the focus issue. (I can use roller ball.)I know I can do an out of band resize and save of my image, but that is not really what I want to do, but some sample code for that would be nice.As soon as I disabled the image on the list view it worked fine again.FYI: This is how I was doing it:String[] from = new String[] { DBHelper.KEY_BUSINESSNAME,DBHelper.KEY_ADDRESS,DBHelper.KEY_CITY,DBHelper.KEY_GPSLONG,DBHelper.KEY_GPSLAT,DBHelper.KEY_IMAGEFILENAME+ ""};int[] to = new int[] {R.id.businessname,R.id.address,R.id.city,R.id.gpslong,R.id.gpslat,R.id.imagefilename };notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);setListAdapter(notes);Where R.id.imagefilename is a ButtonImage.Here is my LogCat:01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.resolveUri(ImageView.java:484)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ImageView.setImageURI(ImageView.java:281)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.CursorAdapter.getView(CursorAdapter.java:150)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.obtainView(AbsListView.java:1057)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.makeAndAddView(ListView.java:1616)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.fillSpecific(ListView.java:1177)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.ListView.layoutChildren(ListView.java:1454)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.AbsListView.onLayout(AbsListView.java:937)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:922)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.LinearLayout.onLayout(LinearLayout.java:920)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.widget.FrameLayout.onLayout(FrameLayout.java:294)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.View.layout(View.java:5611)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.performTraversals(ViewRoot.java:771)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Handler.dispatchMessage(Handler.java:88)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.os.Looper.loop(Looper.java:123)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at android.app.ActivityThread.main(ActivityThread.java:3742)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invokeNative(Native Method)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at java.lang.reflect.Method.invoke(Method.java:515)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)01-25 05:05:49.917: ERROR/AndroidRuntime(3896): at dalvik.system.NativeStart.main(Native Method)01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed I also have a new error when displaying an image: 01-25 22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d01-25 22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri: 01-25 22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.01-25 22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes01-25 22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed


I put the log in a code block to give it scroll bars

2019年10月21日49分59秒

I solved this by avoiding Bitmap.decodeStream or decodeFile and using BitmapFactory.decodeFileDescriptor method.

2019年10月20日49分59秒

The accepted answer on this question is being discussed on meta

2019年10月20日49分59秒

This happens when you don't read the Android developer guides

2019年10月20日49分59秒

This happens because of bad android architecture. It should resize images itself like ios and UWP does this. I don't have to do this stuff myself. Android developers get used to that hell and think it works the way it should.

2019年10月20日49分59秒

This answer is being discussed on meta

2019年10月20日49分59秒

This answer (except the information reached through the link) do not offer much of a solution as for an answer. The important parts of the link should be merged into the question.

2019年10月20日49分59秒

This answer, like the question and the other answers are Community Wiki, so this is something the community can fix by editing, something that does not require moderator intervention.

2019年10月20日49分59秒

Note that 10 may not be the best value for inSampleSize though, the documentation suggests using powers of 2.

2019年10月20日49分59秒

I'm facing the same problem as Chrispix, but I don't think the solution here really solves the problem, but rather sidesteps it.Changing the sample size reduces the amount of memory used (at the cost of image quality, which is probably okay for an image preview), but it will not prevent the exception if a large enough image stream is decoded, of if multiple image streams are decoded.If I find a better solution (and there may not be one) I'll post an answer here.

1970年01月01日00分03秒

You only need an appropriate size to match the screen in pixel density, for zooming in and such you can take a sample of the image at a higher density.

2019年10月20日49分59秒

REQUIRED_SIZE is the new size you want to scale to.

2019年10月21日49分59秒

this solution helped me but the image quality is terrible. I am using a viewfilpper to display the images any suggestions?

2019年10月20日49分59秒

Yes you're right while is not so beautiful. I just tried to make it clear to everyone. Thanks for your code.

2019年10月20日49分59秒

Thomas Vervest - There's a big problem with that code.^ doesn't raise 2 to a power, it xors 2 with the result.You want Math.pow(2.0, ...).Otherwise, this looks good.

2019年10月20日49分59秒

Ooh, that's a very good one! My bad, I'll correct it immediately, thanks for the reply!

2019年10月20日49分59秒

whats , IMAGE_SIZE in this ?

2019年10月20日49分59秒

You are creating two new FileInputStreams, one for each call to the BitmapFactory.decodeStream(). Don't you have to save a reference to each of them so that they can be closed in a finally block?

2019年10月20日49分59秒

BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true; andBitmap.createScaledBitmap(srcBitmap, width, height, false); solved my issue I had with out of memory exception on android 4.0.0.Thanks mate!

2019年10月20日49分59秒

In Bitmap.createScaledBitmap() call you should probably use true as the flag parameter. Otherwise the quality of the image will not be smooth when scaling up. Check this thread stackoverflow.com/questions/2895065/…

2019年10月20日49分59秒

That really is fabulous advice. Wish I could give you an extra +1 for taking Google to task for this amazingly rinky dink bug.I mean... if it's not a bug then the documentation really needs to have some seriously flashing neon signs saying "THIS IS HOW YOU PROCESS PHOTOS", cause I've been struggling with this for 2 years and just now found this post. Great find.

2019年10月20日49分59秒

Scaling your images down definitely helps, but this is an important step and what ultimately solved this issue for me. The problem with just scaling your images is if you have a lot of them, or if the source images are very large then you can still run into the same problem. +1 to you Ephraim.

2019年10月20日49分59秒

As of Lollipop, BitmapFactory.Options.inPurgeable and BitmapFactory.Options.inInputShareable are deprecated developer.android.com/reference/android/graphics/…

2019年10月20日49分59秒

same result out of memeory, actually it wont matter which method you are using it depend upon the number of bytes you are holding on to read the data that gives out of memory.

2019年10月20日49分59秒

What if the path is a url?

2019年10月20日49分59秒

AsyncTask does not necessarily have to be "an instance of an anonymous inner class", and the same goes for Callbackks. You can create a new public class in it's own file that extends AsyncTask, or even a private static class in the same class. They will not hold any reference to the Activity (unless you give them one of course)

2019年10月20日49分59秒

This approach scales the bitmap. But it doesn't solve the OutOfMemory issue because the full bitmap is being decoded anyway.

2019年10月20日49分59秒

I will see if I can look at my old code, but I think it did solve my out of memory issues. Will double check my old code.

2019年10月20日49分59秒

In this example at least, it looks like you aren't keeping the reference to the full bitmap, thus the memory savings.

2019年10月20日49分59秒

For me it did solve the memory issue, but reduced the quality of the images.

2019年10月20日49分59秒

inPurgeable fixed OOM for me.

2019年10月21日49分59秒

Can you explain what this actually does? Simply telling people to add this doesn't help.

2019年10月20日49分59秒

This is a very bad solution. Basically you are not trying to fix the problem. Instead asking android system to allocate more heap space for your application. This will have very bad implications on your app like your app consuming lot of battery power as GC has to run through large heap space to clean up memory and also your app performance will be slower.

2019年10月20日49分59秒

then why android is allowing us add this android:largeHeap="true" in our manifest? Now you are challenging Android.

2019年10月20日49分59秒

According to the API, calling recycle() is not needed.

2019年10月20日49分59秒

Yes, this is wrong.Full solution .. stackoverflow.com/a/24135283/294884

2019年10月20日49分59秒

"and then cache it in a map against its name." How exactly do you cache your images?

2019年10月20日49分59秒

Have you actually tried this? Even though the pixel data is not actually stored within the Dalvik heap, its size in native memory is reported to the VM and counted against its available memory.

2019年10月20日49分59秒

VincentI think its not hard to store them in a Map. I would suggest something like HashMap<KEY, Bitmap> map, where the Key can be a String of the source or anything that makes sense for you. Lets assume you take a path as KEY, you store it as map.put(Path, Bitmap) and recieve it through map.get(Path)

2019年10月20日49分59秒

you prob would want to use HashMap<String, SoftReference<Bitmap>> if you are implementing an image Cache otherwise you may run out of memory anyway - also i dont think that "it allocates memory outside of VM heap which is never reclaimed by GC" is true, the memory is reclaimed as i understand just may be a delay, which is what bitmap.recycle() is for, as a hint to reclaim the mem early...

2019年10月20日49分59秒

that's all Right but i'm using multiple bitmap for draw circle in OnCreate and activity call 4-5 times so how to clear bitmap and how to remove bitmap and create again for second time when activity 0nCreate..

2019年10月20日49分59秒

It is in VM heap since android 2.3+

2019年10月20日49分59秒

looks like imageView really don't recycle bitmap by itself. Helped to me, thanks

2019年10月20日49分59秒

Mike can you add the complete code of imageloader or else can you give me the link of loading bitmap images. If I use recycle on bitmap all my listview is displayed but all the items are shown blank

2019年10月20日49分59秒

Mike can u tell if i do imageView=null before calling into garbage collection is it good or not ?

2019年10月20日49分59秒

TNR I think what you're missing here is that bitmap in the above code is the previous already displayed image, you need to recycle that, clear any references to it, make the imageView forget it as well by setting a tiny replacement, gc(); and after all this: load your NEW image to bitmap and display it, the ... in the above code.

2019年10月20日49分59秒

This is wrong. You should always clear your imageView content BEFORE recycling bitmap (instead of while it is actually displayed and being used).

2019年10月20日49分59秒

To anyone using this: I just fixed a bug:"int scaledBitmapHeight = scaledBitmap.getWidth();" is wrong (obviously. I replaced it with "int scaledBitmapHeight = scaledBitmap.getHeight();"

2019年10月20日49分59秒

I can't thank you enough for this!I was chasing the wrong problem before seeing this.Question for you though: Since each or my list rows has a unique name and photo I had to use a convertView array to retain each of the rows' values.I couldn't see how using a single variable would allow you to do so.Am I missing something?

2019年10月20日49分59秒

Love your solution! I've also spend hours of solving this bug, so annoying!Edit: Sadly, the problem still exists when I change my screen orientation in landscape mode...

2019年10月20日49分59秒

This finally helped with me along with:-BitmapFactory.Options options = new BitmapFactory.Options();options.InPurgeable = true; options.InSampleSize = 2;

2019年10月20日49分59秒

So not true, this happens on MANY Samsung devices...

2019年10月20日49分59秒

I am glad you mentioned Picasso, because it makes loading images much easier. Especially remotely stored ones.

2019年10月20日49分59秒

+1 for looking at available memory

2019年10月20日49分59秒

And if setImageURI still getting exception then refer this stackoverflow.com/questions/15377186/…

2019年10月20日49分59秒

Nice, think it would be better to use a Loader instead of Async Task?

2019年10月20日49分59秒

How about Bitmap.Config.ARGB_565? If high quality is not critical.

2019年10月20日49分59秒