On the memory optimization of Android application and the handler memory leaking problem _android

Source: Internet
Author: User
Tags garbage collection message queue object object static class

One, Android Memory basics
Physical memory and process memory
physical memory is the RAM on the mobile device, and when you start an Android program, a Dalvik VM process is started and the system assigns it a fixed amount of memory (16m,32m), which maps to a region of RAM. Then the Android app will run in this space. In Java, this space is divided into stack memory and heap heap memory. A reference to an object in a stack that holds the actual object data in the heap.
In the program running will create objects, if not reasonable management of memory, such as not timely recovery of invalid space will cause memory leaks, serious words may lead to the use of memory over the system allocated memory, that is, memory overflow oom, resulting in the program cotton even direct exit.

Memory leaks (Memory leak)
A Java memory leak is a process in which some objects (garbage objects) have no use value, but they can be referenced directly or indirectly to GC roots, resulting in the inability to be reclaimed by GC. The GC mechanism of the Dalvik VM (garbage collection mechanism) is automatically recycled when memory footprint is excessive, causing a memory overflow oom.

Memory Overflow Oom
The overflow occurs when the application requests a Java heap space that exceeds the Dalvik VM heapgrowthlimit.
Note: Oom does not mean that there is not enough memory, as long as the requested heap exceeds the Dalvik VM heapgrowthlimit, even sufficient memory can overflow. The effect is to allow more process resident memory.

What will the system do if there is not enough RAM?
Android's memory killer kills lower-priority processes, allowing higher-priority processes to get more memory.

Android Default memory recycle mechanism

Process priority: foreground process, visible process, service process, background process, empty process;
If the user presses the home key to return to the desktop, the app becomes the background process, and if it returns, it becomes the empty process
Activitymanagerservice directly manages the allocation of memory resources for all processes. All processes need to request or free memory through the Activitymanagerservice object.
Garbage collection is not performed on a regular basis. When the memory is not enough, it will traverse the heap space, delete the garbage object.
The larger the heap memory, the longer the GC

Second, optimize
Bitmap optimization
bitmap consumes a lot of memory, and in Android, when reading bitmap, the image stack typically assigned to the virtual machine is only 8M, so it often causes oom problems. It is therefore necessary to optimize for the use of bitmap:

Picture display: Load the appropriate size of the picture, such as showing thumbnails of the place do not load large graphics.
Picture Recycling: Use the bitmap in time, use Bitmap.recycle () recycle.
Question: Does Android have a garbage collection mechanism of its own? Why you should manually recycle here. The
Bitmap object is not generated by new, but is produced by Bitmapfactory. And the source can be found by invoking JNI to generate bitmap objects (Nativedecodestream () and other methods). So, loading bitmap into memory consists of two parts, Dalvik memory and Linux kernel memory. The former will be automatically recycled by the virtual machine. The latter must use the Recycle () method, internal call nativerecycle () to let Linux kernel recycling.
Catch Oom Exception: program to set the emergency handling mode if oom occurs.
Picture caching: Memory cache, hard disk cache, and so on
picture compression: The direct use of ImageView display bitmap will make up a lot of resources, especially when the picture is larger, easy to occur oom. You can use bitmapfactory.options to compress pictures.
Picture pixels: The android default color mode is argb_8888, displays the highest quality and consumes the most memory. If the request is not high, can adopt rgb_565 model. Picture size: Picture length * Width * Number of bytes occupied by the unit pixel
argb_4444:2byte memory per pixel
argb_8888:4byte memory per pixel (default)
rgb_565:2byte memory per pixel
object reference type

Strong reference Strong:object Object=new Object (). When there is not enough memory, the Java virtual machine would rather throw a oom memory overflow exception and not easily reclaim the strong reference object to solve the out-of-memory problem;
Soft reference soft: Only when the memory reaches a certain threshold will be recycled, often used for caching;
Weak reference weak: Recycle as long as it is scanned by GC threads;
Virtual reference
If you want to avoid oom occurrences, use soft reference objects, which are recycled when memory is running low, and if you want to reclaim some of the larger memory objects as quickly as possible, such as bitmap, you can use weak references to be quickly recycled. However, if you want to cache bitmap, do not use weak references, because the GC will soon be reclaimed, causing the cache to fail.
About Java object reference types, you can participate in another article
Pools Pool

Object pooling: If an object needs a large resource overhead when it is created, you can put it into the object pool, save the object, and use it directly the next time it is needed without creating the object again. Of course, the maintenance object pool also needs a certain cost, so to measure.
Thread pools: Similar to object pooling, putting thread objects in a pool for reuse, reducing the overhead of creating threads over and over again.

Three, handler memory leakage analysis and solution
1. Introduction
First, please browse the following handler code:

public class Sampleactivity extends activity {
 private final Handler Mleakyhandler = new Handler () {
  @Override 
   
    public void Handlemessage (Message msg) {
   //...}} 
  }


   

This is a very common piece of code when using handler. However, it can cause a serious memory leak problem. In actual writing, we often get the following warning:

In Android, Handler classes should is static or leaks might occur.
So how does the handler cause a memory leak?

2, analysis
(1), Android angle
when the Android application starts, the framework creates a Looper object for the application's main thread. This Looper object contains a simple message queue and is able to loop through the messages in the queue. These messages include most application framework events, such as activity lifecycle method calls, button clicks, etc., which are added to message queues and processed individually.
In addition, the Looper object of the main thread accompanies the entire lifecycle of the application.

Then, when a handler object is instantiated in the main thread, it is automatically associated with the message queue of the main thread looper. All message messages sent to the message queue will have a reference to Handler, so when looper to process the message, it will callback [Handler#handlemessage messages] (http:// Developer.android.com/reference/android/os/handler.html#handlemessage (Android.os.Message) method to process messages.

(2), Java angle
in Java, non-static inner classes and anonymous classes can potentially refer to the external classes to which they belong. However, static inner classes are not.

(3), the source of leakage
Please browse the following code:

public class Sampleactivity extends activity {

 private final Handler Mleakyhandler = new Handler () {
  @Override 
   
    public void Handlemessage (Message msg) {
   //...
  }
 }

 @Override
 protected void onCreate (Bundle savedinstancestate) {
  super.oncreate (savedinstancestate);

  Post A and delay its execution for minutes.
  Mleakyhandler.postdelayed (New Runnable () {
   @Override public
   void Run () {/*/* ... */}
  }, 1000 *); 
    //go back to the previous activity.
  Finish ();
 }



   

When the activity finishes (finish), the delay message inside is kept in the main thread's message queue for 10 minutes before being processed. And, as you know, this message holds a reference to handler, and handler holds a potential reference to its outer class (here, sampleactivity). This referential relationship remains until the message is processed, which prevents the sampleactivity from being reclaimed by the garbage collector, while causing the application to leak.
Note that the Runnable class in the above code-a Non-static anonymous class-also holds a reference to its external class. Which also leads to leaks.

3, Leakage solution
first, the memory leak source is identified above:

Whenever there is an unhandled message, the message references handler, and the Non-static handler references the outer class, which is the activity, which causes the activity to be recycled, causing the leak;
the Runnable class belongs to a Non-static anonymous class and also references an external class.
To resolve the problems encountered, let us be clear: static internal classes do not hold references to external categories. So, we can put the handler class in a separate class file, or use static inner classes to avoid leaks.
In addition, if you want to invoke the external class activity within the handler, you can point to the activity within the handler using a weak reference so that the unification does not cause a memory leak. The
runnable for anonymous classes can also be set to static classes. Because static anonymous classes do not hold a reference to an external class.

public class Sampleactivity extends activity {/** * instances of static inner classes don't hold an implicit * re
  Ference to their outer class.

  * * private static class MyHandler extends Handler {private final weakreference<sampleactivity> mactivity;
  Public MyHandler (sampleactivity activity) {mactivity = new weakreference<sampleactivity> (activity);
   @Override public void Handlemessage (message msg) {sampleactivity activity = mactivity.get ();
  if (activity!= null) {//...}

 } private final MyHandler Mhandler = new MyHandler (this);
  /** * Instances of anonymous classes do not hold a implicit * reference to their outer the class when they "static".

 * * private static final Runnable srunnable = new Runnable () {@Override public void run () {/* ... * *}};

  @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Post a message and delay it execution for ten minuteS. mhandler.postdelayed (srunnable, 1000 * 60 * 10);
  Go back to the previous activity.
 Finish ();

 }
}

4, summary
Although the difference between static and Non-static classes is small, it is essential for Android developers to understand. At least we should be clear that if an internal class instance's lifecycle is longer than activity, then we should never use non-static internal classes. The best practice is to use a static inner class and then use a weak reference in that class to point to the activity in which it is located.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.