*activitys, Threads and memory leaks

Source: Internet
Author: User

One common difficulty in Android programming is to coordinate the activity's life cycle and long-running tasks (Task), and to avoid possible memory leaks. Consider the code of activity below to open a thread and loop through the task as it starts.

1/**2 * An example of how a thread can survive configuration changes (configuration changes will cause the activity of the Gen 3 * thread to be destroyed).  The activity in the code is compromised because the thread is a real 4 * instance of an anonymous class that implicitly holds an external activity instance and therefore prevents activity 5 * from being recycled. 6*/7 Public classMainactivityextendsActivity {8 9@Override10protected voidonCreate (Bundle savedinstancestate) {11Super. OnCreate (savedinstancestate);12Exampleone ();13   }14 15Private voidExampleone () {16NewThread () {17@Override18 Public voidrun () {19 while(true) {Systemclock.sleep (1000);21st         }22       }23}.start ();24   }25}

When a configuration changes (such as a portrait-to-screen toggle), it causes the entire activity to be destroyed and recreated, it is easy to assume that Android will clean up and reclaim the memory associated with activity and the threads it is running. However, this is not the case. Both lead to memory leaks and are not recycled, and the result is that performance can drop significantly.

How to let an activity leak

If you read my previous article about handler and internal classes, then the first memory leak should be easy to understand. In Java, non-static anonymous classes implicitly hold references to their external classes. If you are not careful, saving this reference may result in the activity being saved when it can be recycled by GC. Activity holds a reference to their entire view inheritance tree and all the resources it holds, so if you leak one, a lot of memory will be compromised.

This problem is exacerbated by configuration changes, which send a signal that the activity is destroyed and recreated. For example, after 10 screen changes based on the code above, we can see (using Eclipse memory Analyzer) that each activity object remains in memory due to implicit references:

Figure 1. Activity instances that persist in memory after 10 configurations have changed

Each time the configuration changes, the Android system creates a new activity and allows the old activity to be recycled. However, the threads that the old activity references are implicitly held to prevent them from being recycled. So every time a new activity is disclosed, all the resources associated with them will not be recycled.

The workaround is also simple, as we identify the root cause of the problem, so long as the thread is defined as the private static inner class, as follows:

1/**2 * This example prevents the activity from releasing 3 * Dew by declaring the thread instance as the internal class of the private static type, but the thread still survives the configuration change. The DVM has a 4 * reference to all running threads, regardless of whether they can be garbage collected, and how long the thread survives and when 5 * is not related to the life cycle of the activity. 6 * The active thread will continue to run until the system destroys your application. 7*/8 Public classMainactivityextendsActivity {9 10@Override11protected voidonCreate (Bundle savedinstancestate) {12Super. OnCreate (savedinstancestate);13exampletwo ();14   }15 16Private voidExampletwo () {17NewMyThread (). Start ();18   }19 20Private Static classMyThreadextendsThread {21st@Override22 Public voidrun () {23 while(true) {Systemclock.sleep (1000);25       }26     }27   }28}

The new thread does not implicitly hold the activity reference, and the activity becomes recyclable after the configuration has changed.

How to make a thread leak

The second problem is that whenever a new activity is created, it causes a thread to leak and not be recycled. In Java, thread is the GC root, which means that the Dalvik Virtual machine (DVM) in the system holds a strong reference to all active threads, which leads to the retention of the thread and the condition that can be recycled. So you have to think about how to stop the background thread. Here is an example:

1/**2 * As in Example 2, except this time we implement the mechanism of canceling the thread, so as to ensure that it does not leak. 3 * OnDestroy () is often used to cancel threads before activity is rolled out. 4*/5 Public classMainactivityextendsActivity {6PrivateMyThread Mthread;7 8@Override9protected voidonCreate (Bundle savedinstancestate) {10Super. OnCreate (savedinstancestate);11Examplethree ();12   }13 14Private voidExamplethree () {Mthread =NewMyThread ();16Mthread.start ();17   }18 19/**20 * Static inner classes do not implicitly hold references to their external classes, so activity instances are not compromised in configuration change 21 **/23Private Static classMyThreadextendsThread {24Private BooleanMrunning =false;25 26@Override27 Public voidrun () {Mrunning =true;29 while(mrunning) {Systemclock.sleep (1000);31       }32     }33 34 Public voidClose () {Mrunning =false;36     }37   }38 39@Override40protected voidOnDestroy () {41Super. OnDestroy ();42mthread.close ();43   }44}

In the above code, we closed the thread in OnDestroy () to ensure that the thread is not accidentally compromised. If you want to save the state of the thread when the configuration changes (instead of shutting down and recreating a new thread each time). Consider using a fragment that can be retained (not destroyed in configuration changes), without a UI, to perform long-time tasks. Look at my blog, called "Using fragment to solve the problem of screen rotation (state change) state can not be maintained," there is an example of the implementation of this. The API demo also has a comprehensive example.

Summarize

The relationship between the activity life cycle and long-running tasks in Android can be difficult and can lead to memory leaks. Here are some general recommendations worth considering:
the use of static inner classes rather than non-static is preferred . Each instance of a non-static inner class will have a reference to its external activity instance. When activity can be recycled by GC, external activity references stored in non-static inner classes can cause garbage collection to fail. If your static inner class needs to host activity references to execute something, you will encapsulate this reference in one WeakReference and avoid accidentally causing the activity to leak.

don't assume that Java will eventually clean up running threads for you . In the example above, it is easy to mistakenly assume that the activity will be recycled after the user exits the activity, and that any thread associated with the activity will be recycled as well. In fact, that's not true. Java threads continue to run until they are explicitly closed or the entire process is killed by the Android system. Therefore, be sure to remember to implement the corresponding cancellation policy for the background thread and use reasonable measures when the activity life cycle event occurs.

consider whether you should really use threads . The Android framework provides a number of classes designed to simplify the development of background threading for developers. For example, consider using loader instead of threading when you need to do some short-time Asynchronous background task query class tasks with the activity lifecycle. Consider using service, and then use Brocastreceiver to feed back progress and results to the UI. Finally, remember that all of the threads discussed in this article also apply to Asynctask (because the Asynctask class uses Executorservice to perform its tasks). However, since asynctask should only be used for a short period of time (up to a few seconds, referring to the document), it will not cause a problem as large as activity or thread leaks.

The source code in this article is available for download from GitHub. The sample programs in the article can be downloaded from Google Play.

Links: Activitys, Threads, & Memory Leaks

*activitys, Threads and memory leaks

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.