Memory leaks caused by using thread in activity

Source: Internet
Author: User

  • Original link: activitys, Threads, & Memory Leaks
  • Original Author: Alexlockwood
  • Development technology Front www.devtf.cn
  • Translator: Chaossss
  • Reviewer: yinna317
  • Status: Complete

Note: The source code for this blog post can be downloaded on GitHub!

The most common problem with Android development is to coordinate time-consuming tasks during the Activity's life cycle, and to avoid performing tasks that cause imperceptible memory leaks. Read the code below and write a simple activity,activity that starts a thread and loops through the tasks in that thread.

    /** * Example shows us when the configuration of an activity changes (a configuration change causes the activity instance to be sold* destroyed) survived. In addition, the context of the Activity is part of a memory leak because each thread is initially* into anonymous internal classes, so that each thread holds an implicit reference to an external Activity instance, making* Activity is not recycled by Java's garbage collection mechanism.      */       Public class mainactivity extends Activity{@Override      protected void onCreate(Bundle savedinstancestate) {Super.OnCreate (savedinstancestate);      Exampleone (); }Private void Exampleone() {New Thread() {@Override           Public void Run() { while(true) {Systemclock.Sleep +); }          }        }.Start (); }    }

Changes in the activity configuration will cause the activity to be destroyed and a new activity will be created, and we always feel that the Android system would clean up everything related to the destroyed activity, such as recovering the memory associated with the activity, activity Thread of the line, etc... However, the reality is always very brutal, just mentioned these things will not be recycled, and lead to memory leaks, which significantly affect the performance of the application.

The source of Activity memory leaks

If you've read a blog post I wrote about Handler and the inner class, you know what I'm going to say next. In Java, a non-static anonymous inner class holds an implicit reference to its outer class, and if you have not considered this, storing the reference causes the Activity to be retained rather than being reclaimed by the garbage collection mechanism. The Activity object holds a reference to its View layer and all associated resource files, in other words, if your memory leak occurs in the activity, you will lose a lot of memory space.

The problem is even worse when the activity configuration changes, because the configuration change of the activity means that the Android system will destroy the current activity and create a new activity. For example, when you use the app, you perform 10 horizontal/vertical screens, and every change in the direction executes the following code, and we'll see that each Activity object is kept in memory by leaving an implicit reference (as can be seen using Eclipse's memory analysis tool).

Each configuration change will cause the Android system to create a new activity and give the pre-change activity to the garbage collection mechanism for recycling. However, because the thread holds an implicit reference to the old activity, the activity is not reclaimed by the garbage collection mechanism. Such a problem would result in a memory leak for each new activity, and all resource files related to the activity will not be recycled, and the memory leaks are much more predictable.

See here may you will be very frightened, very frightened, very helpless, then what should we do ... Don't panic, the solution is very simple, since we have identified the root cause of the problem, then the right remedy: We declare the thread class as private static inner class can solve this problem:

     /*** Example avoids a memory leak problem with Activity context by declaring a thread class as private by a static inner class, but* The thread will still execute after the configuration has changed. The reason is that the DVM virtual machine holds a reference to all running threads, regardless* Whether these threads are recycled is unrelated to the Activity's lifecycle. The running thread will only continue to run until* Android system kills the entire application process      */      Public class mainactivity extends Activity{@Override      protected void onCreate(Bundle savedinstancestate) {Super.OnCreate (savedinstancestate);      Exampletwo (); }Private void Exampletwo() {New MyThread().Start (); }Private Static class MyThread extends Thread{@Override         Public void Run() { while(true) {Systemclock.Sleep +); }        }      }    }

With the code above, the new thread never holds an implicit reference to an external activity, and the activity is recycled after the configuration changes.

Root cause of thread memory leaks

The second issue is: For each new activity, a memory leak occurs if a thread in the activity occurs. In the Java thread is the source of the garbage collection mechanism, that is, the DVM virtual machine in the running system always causes the hardware to hold a reference to all the running states of the process, resulting in the running state being never recycled. Therefore, you must implement the destruction logic for your background thread! Here's a workaround:

    /*** Except that we need to implement the destruction logic to ensure that the thread does not have a memory leak, the other code is the same as Example 2. When exiting the current* It's a good idea to use the OnDestroy () method to end your running thread before Activity .     */     Public class mainactivity extends Activity{Private MyThreadMthread;@Override      protected void onCreate(Bundle savedinstancestate) {Super.OnCreate (savedinstancestate);      Examplethree (); }Private void Examplethree() {Mthread= New MyThread(); Mthread.Start (); }/*** A private static inner class does not hold a reference to its external class so that the Activity instance does not occur when the configuration changes* Storage and leakage       */      Private Static class MyThread extends Thread{Private BooleanMrunning= false;@Override         Public void Run() {mrunning= true; while(mrunning) {Systemclock.Sleep +); }        } Public void Close() {mrunning= false; }      }@Override      protected void OnDestroy() {Super.OnDestroy (); Mthread.Close (); }    }

With the code above, we ended the thread in the OnDestroy () method, ensuring that no unexpected thread's memory leaks were occurring. If you want to keep the thread after the configuration changes (instead of creating a new thread every time the Activity is closed), I recommend that you use Fragment to complete the time-consuming task. You can go through my previous blog post, a known as "handling Configuration changes with fragments" should be able to meet your needs, in the API demo also provides a good understanding of the examples to explain the relevant concepts for you.

Conclusion

During the Android development process, it can be difficult to reconcile time-consuming tasks during the Activity lifecycle, and you can inadvertently cause a memory leak problem. Here are some tips to help you prevent a memory leak:

  • use static inner classes instead of non-static inner classes whenever possible. each non-static inner class instance holds a reference to an external class, and if the reference is an activity reference, the activity will not be reclaimed when it is destroyed. If your static inner class needs a reference to a related activity to ensure that it works, then you need to make sure that you are using a weak reference to the activity in your object, or your activity will have an unexpected memory leak.

  • don't always think about the Java garbage collection mechanism to help you with all the memory recycling issues. like the example above, we thought that the garbage collection mechanism would help us to reclaim the memory we didn't need to use, for example: we need to end an Activity, and then its instance and the associated thread are recycled. But the reality is not going to be like our script. Java threads will survive until they are explicitly closed, or their processes are killed by the Android system. So, implementing the destroy logic for your background thread is a detail that you have to keep in mind when you use threads, and in addition, you design the destruction logic based on the Activity's life cycle to avoid bugs.

  • consider whether you really need to use threads. the framework layer of Android apps gives us a lot of classes that make it easy for developers to perform background operations. For example, we can use Loader instead of using threads to perform short asynchronous background query operations during the Activity's life cycle, and consider using Service to notify the broadcastreceiver of the structure to the UI. Finally, keep in mind that this blog post discussion of threads also applies to asynctask (because Asynctask uses Executorservice to perform its tasks). However, although executorservice can only be used in a short operation (the document says up to a few seconds), the Activity memory leaks caused by these methods should never occur.

The source code for this blog post can be downloaded from GitHub, and you can also download APK for Google Play.

Memory leaks caused by using thread in activity

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.