Exception from memory Exception when working with raster images

I am working on an application in which I have images loaded asynchronously for SlideShows. One slide show contains 10 slides, so 10 images are uploaded when you open the slide show. After I scroll through 10-15 slide shows, I start to receive warnings about memory and after an exception as a result of failures in the trace and application.

Here is the trace:

12-23 12:23:53.124: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process. 12-23 12:23:53.134: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11913KB, Bitmap Size=11407KB 12-23 12:23:53.134: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes 12-23 12:23:53.134: DEBUG/skia(3067): --- decoder->decode returned false 12-23 12:23:53.134: WARN/dalvikvm(3067): threadid=46: thread exiting with uncaught exception (group=0x400259f8) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): FATAL EXCEPTION: Thread-1016 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:468) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:332) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at com.nbcu.myApp.appsupport.AsyncImageLoader.loadImageFromUrl(AsyncImageLoader.java:98) 12-23 12:23:53.134: ERROR/AndroidRuntime(3067): at com.nbcu.myApp.appsupport.AsyncImageLoader$2.run(AsyncImageLoader.java:70) 12-23 12:23:53.154: WARN/ActivityManager(96): Force finishing activity com.nbcu.myApp.activities/com.nbcu.myApp.controllers.StoriesListController 12-23 12:23:53.224: ERROR/dalvikvm-heap(3067): 45850-byte external allocation too large for this process. 12-23 12:23:53.234: DEBUG/SurfaceFlinger(96): Layer::setBuffers(this=0x2fabc0), pid=96, w=1, h=1 12-23 12:23:53.234: ERROR/dalvikvm(3067): Out of memory: Heap Size=13127KB, Allocated=11948KB, Bitmap Size=11407KB 12-23 12:23:53.234: ERROR/GraphicsJNI(3067): VM won't let us allocate 45850 bytes 12-23 12:23:53.234: ERROR/Error(3067): Message = java.lang.OutOfMemoryError: bitmap size exceeds VM budget 

Image Upload Code:

 public void run() { Looper.prepare(); for (int i = 0; i < slides.size(); i++) { try { final SlideShowItem story = slides.get(i); if (story.getImage() == null) { Drawable cachedImage = Utils.database.getRSSImage(Constants.StoriesTable, story.getItemId()); if (cachedImage != null) { story.setImage(cachedImage); } else { cachedImage = asyncImageLoader.loadDrawable(story.getImagePath(), new ImageCallback() { public void imageLoaded(Drawable imageDrawable, String imageUrl) { story.setImage(imageDrawable); Utils.database.storeRSSItemImage(Constants.StoriesTable, imageDrawable, story.getItemId()); } }); } } Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } } Looper.loop(); } 

Code for loadDrawable ():

 public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) { final Handler handler = new Handler() { public void handleMessage(Message message) { imageCallback.imageLoaded((Drawable) message.obj, imageUrl); } }; new Thread() { public void run() { Drawable drawable = loadImageFromUrl(imageUrl); // System.out.println("image url: " + imageUrl); if (drawable != null) { Message message = handler.obtainMessage(0, drawable); handler.sendMessage(message); } } }.start(); return null; } 

and code for loadImageFromURL ():

  public static Drawable loadImageFromUrl(String url) { Drawable image = null; try { InputStream in = (java.io.InputStream) new java.net.URL(url).getContent(); if (in != null) { image = Drawable.createFromStream(in, "image"); } in.close(); } catch (Exception ex) { // ex.printStackTrace(); Log.v("Exception ", "Asyn Image.In LoadImageFromURL Message: " + ex.toString()); } return image; } 

After downloading the images, they are cached. I cannot find a workaround to avoid this exception. What could be the reason? I also tried to set the images as images when the activity is destroyed, but nothing has been done for me? Any help is appreciated. Thank you in advance.

+4
source share
3 answers

Android is a mobile OS. It has limited memory, so you cannot cache all .size () slides. I assume the size is> 15. For example, im running the FastCV algorithm with an HD image as markers, 250,000 x 180,000 pixels, and if I run the program on a PC, work fine if I do this on a mobile phone, no, because there is not enough memory .

I think that you can solve the problem, if only cachΓ© 10 - 15 images, depends on their size. If scrolling, then cache the new one in the memory already in use.

+5
source

Consider zooming out cached images to the size of the views with which they are used. For example, you can use the following approach in your loadImageFromUrl(String url) method:

 // Determining the original size of the image: BitmapFactory.Options optnsSizeOnly = new BitmapFactory.Options(); optnsSizeOnly.inJustDecodeBounds = true; InputStream inputStreamSizeOnly = (java.io.InputStream) new java.net.URL(url).getContent(); BitmapFactory.decodeStream(inputStreamSizeOnly, null, optnsSizeOnly); int widthOriginal = optnsSizeOnly.outWidth; // Determining the scale ratio. // Note, it just an example, you should use more sophisticated algorithm: int ratio = widhtOriginal / widthView; // widthView is supposed to be known // Now loading the scaled image: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = ratio; InputStream inputStream = (java.io.InputStream) new java.net.URL(url).getContent(); Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); 
+4
source

You should use a kind of tweaked lazy initialization . I would like to use 3 images at a time, the displayed image and the next two. Thus, when the user views image1, image2 and image3 are already in memory. When the user navigates to image2, image4 should be loaded into the previous buffer image1 (image 3 is still in memory) I hope this helps

+2
source

Source: https://habr.com/ru/post/1387696/


All Articles