Recently, I have developed applications on xoom. I used images for the UI design and multiple activities. If you don't feel anything at first, you can do it. After the execution is complete, it is okay to start running the first three activities. Everything is OK. However, OOM (out of memory) often occurs in the last activity. Because in the last activity, you need to open a PDF file, then render, along with multi-touch, reander's pdf page scaling, because the reander image itself is relatively large (for example, if the PDF is zoomed twice the current screen, the memory occupied by the PDF image is 1280*800*4*2/(1024*1024), which is about 8 Mb, the image will be cached in the cache (to prevent users from getting stuck in the operation), it will always cause OOM exceptions.
Oh, my God! Most afraid of this situation, the memory heap size limit of Android is a crash. Although IOS is also known as an application with a memory limit, however, in actual use, the memory used by an application can usually exceed 100 MB, so it is easy to develop an application with satisfactory performance.
Where does my application use so much memory? Because the default heap size of android3.0 is 48 MB, it is still acceptable. How can I use OOM when my application does not run a few times? No way, you can only analyze it through ddms. In ddms, "Update Heap"-"cause GC" is used to view the memory usage of the application and find that every time you enter an activity, 1-The value of byte array (byte [], Boolean []) will always increase accordingly. During the last activity, nothing will be done. The heap size is almost 30 mb, oh... Why... Calm down... Through analysis, 1-byte
Array is the space occupied by bitmap, which indicates that there are constantly new bitmaps in the memory. Because the UI uses a lot of images, such as large background images and button images, it seems that these images will all exist in the memory, even if the current activity has been destroyed into the next activity, the image resources of the previous activity are not destroyed.
The reason is found, but it doesn't make sense. Because in oncreate, I use mbtn. setbackgroundresource (R. drawable. splash) sets the background image for the control, and uses (bitmapdrawable) mbtn in ondestroy. getbackground ()). setcallback (null) clears the background image. In principle, image resources should have been cleared up. Think twice about the source code of Bitmap. The function of bitmap is to destroy the Java object bitmapdrawable. To improve the efficiency of Android, bitmap's real bitmap data is written in C in ndk, therefore, setcallback cannot destroy bitmap data. You should call bitmap's recycle () to clear the memory.
Therefore, it is assumed that the ondestroy is added (bitmapdrawable) mbtn. getbackground ()). getbitmap (). recycle (). This way, the memory condition is very good. No matter which activity is used, the resources used are only used by the current activity, and it will not be like the last activity, all previously used resources are accumulated in the memory. The memory used for every activity resource and class is about 10 MB, which is already ideal (of course, it will not work if it is in a lower Android version such as 1.5 or 16, this requires re-architecture of the Application), which can reserve a large amount of memory for the display PDF.
However, a new problem occurs again. When the previous activity is returned, an exception "try to use a recycled bitmap" will occur. This is really a waste of money, the heart of the frustrated... No way. Continue the analysis. It seems that it is caused by recycle. The bitmap must be referenced in the memory. When the previous activity is returned, the current situation is caused because the bitmap data is actually destroyed. After reading the source code of setbackgroundresource, I suddenly realized that android has implemented cache for resources directly loaded by resource ID, in this way, you can directly obtain the resource from the cache when you need the resource again next time. This is also a consideration for efficiency. However, this also causes the used resources to be in the memory. This design is not very suitable for applications that use many large image resources, in this way, the application's memory peak is very high. After reading the SDK, I used:
Bitmap Bm = bitmapfactory. decoderesource (this. getresources (), R. drawable. Splash );
Bitmapdrawable BD = new bitmapdrawable (this. getresources (), BM );
Mbtn. setbackgrounddrawable (BD );
To replace mbtn. setbackgroundresource (R. drawable. Splash ).
Used for destruction:
Bitmapdrawable BD = (bitmapdrawable) mbtn. getbackground ();
Mbtn. setbackgroundresource (0); // do not forget to set the background to null to avoid the used a recycled bitmap error when the ondraw refreshes the background.
BD. setcallback (null );
BD. getbitmap (). Recycle ();
After this adjustment, it avoids caching all resources in the application and saves valuable memory. In fact, this will not cause too much efficiency problems. After all, it is very fast to reload resources, it will not have a serious impact on performance. In xoom, I didn't feel any difference from the previous one.
In short, using a large number of bitmaps on Android is a pain point, and the existence of memory restrictions is a huge bottleneck for applications. However, you don't need to pay for food because of the food occupation. In fact, you can understand the mechanism in it. Applications can break through these restrictions. This is only one of the processing methods. You can also consider the insamplesize of bitmapfactory. options to reduce memory usage.