简体   繁体   中英

Android ListView Row Background's causing OutOfMemory Issue

I have a fragment which pulls down data from a webservice and displays this in a ListView. I have 10 different selectors which can are used for the Row Backgrounds. The background are repeated once it loops.

The issue I am facing is that the device (Galaxy Nexus!) cannot handle displaying all of these backgrounds. When I set the background via setbackgroundResource the OS is constantly calling the GC to free up memory, which makes the ListView scrolling extremely choppy.

So I tried to cache the Drawables used instead. I see an improvement, but the device will eventually throw an OutOfMemory exception bedcause of how many Drawables are cached. To give an example of how many are cached, I need all 10 selectors which contain two drawables in each, plus a first and last as these are different. This is 24 drawables in memory.

Now, I was thinking it could be the size of the images I am using, and that I need to scale them down and just stretch the proportionally, but im not sure if this will work.

Any suggestions? I have spent a couple of days working on this non-stop, and have not found a viable/close solution.

Thanks

Adam

Mimminito,

The issue you are describing plagues many a developer on the Android platform. The reason for this is that when Google implemented View Drawables, they had to make a valid assumption that the previous Drawable may need to be kept. This is because more and more applications on an increasing number of platforms require this behavior.

Ultimately, there are several ways to mitigate the issues, but there is no one catch all solution.

  1. When you replace the backgrounds, get the original background. If it is a Bitmap, recycle() it. If it is a Drawable, set the reference to null and remove its Callback via setCallback (This is especially important when you are changing orientations or switching Activities).

  2. Graphics are one of the most memory consuming resources. If you are using a Drawable or Bitmap, it uses 4 bytes per pixel. BUT if the image has to be resized to display properly, it actually uses quite a bit more whether the app is upsizing or downsizing. Creating the graphic in high resolution is awesome, but for mobile devices, you want to scale it to the sizes you are actually going to be using.

  3. If you are using a lot of graphics, you might consider using only the ones that are going to be visible. That is, if you have 32 items, but only 3 are visible, only load the 3 that are visible and maybe some immediate neighbors. Lazy Loading can be implemented for a number of the standardized controls.

  4. I recommend looking at .9.png files. These are great for optimizing graphics.

  5. If your buttons have text, do not draw it on the graphic file. Allow Android to place the text on the graphics file. Its treated much differently and the memory consumption is reduced considerably. While it may not be as aesthetically pleasing, it will increase reliability (which is why you are here)

  6. In some cases, it may be desirable to have the graphics be flat bitmaps, rather than a compressed format. This reduces load on the processor and memory, but at the cost of file size. This is because the compressed formats must be decompressed in memory to be used anyway, but the memory isn't freed until the file is actually closed. (This doesn't even include the memory for the runtime code used to decompress it, and is even MORE costly when the app has to resize the graphic).

  7. Putting in some extra System.gc() statements can help ease the load, but it isn't reliable as it only tells the system that it is ready for a garbage collection at its earliest convenience.

  8. Finally, you can have mutliple sizes according to the resolutions of the device. This is information you can transmit via your app. This is how we have to do multiple device support in a local application.

All of these suggestions may help, but its a lot of information. Hopefully, I gave you enough for you to implement a solution that will cater to your needs.

Hope this helps, FuzzicalLogic

Maybe you are setting the cacheColorHint to transparent (if you have a fixed background image ): android:cacheColorHint="#00000000" . For me it was also calling the GC to many times.

I found that setting the following properties disables android's list view caching and the list scrolls smooth (the GC is not called that often any more):

android:scrollingCache="false"
android:animationCache="false"

Also if u want to get rid of the default selection color use this:

android:listSelector="#00000000"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM