Android Memory leakage ., Android Leakage

Source: Internet
Author: User

Android Memory leakage ., Android Leakage

Recently, during code maintenance, we found that a custom View (this View is created in the doInBackground of an AsyncTask worker thread and added to the window in the onPostExecute thread of the UI thread) often leaks the memory, as a result, the referenced Activity cannot be released, and every time it exits and then enters the Activity, the Activity object will be + 1.

Package com. xxx. launcher. view; import android. content. context; import android. util. log; import android. view. view; public class WeatherTextView extends SkinTextView {public WeatherTextView (Context context ){
Super (context); postDelayed (mShowCityRunnable, 200); // This step has a problem} @ Override protected void onWindowVisibilityChanged (int visibility) {super. onWindowVisibilityChanged (visibility); if (visibility = View. VISIBLE) {post (mShowCityRunnable) ;}@override protected void onDetachedFromWindow () {super. onDetachedFromWindow (); onCancel () ;}; public void onCancel () {removeCallbacks (callback);} private Runnable mShowCityRunnable = new Runnable () {@ Override public void run () {Log. I ("mShowCityRunnable ------- TAG", "run" + mShowCityRunnable); setText (city );}};}

 

Public boolean post (Runnable action) {Handler handler; AttachInfo attachInfo = mAttachInfo; if (attachInfo! = Null) {handler = attachInfo. mHandler;} else {// Assume that post will succeed later ViewRootImpl. getRunQueue (). post (action); return true;} return handler. post (action );}

In the post () function comment, it clearly says: This method can be invoked from outside of the UI thread only when this View is attached to a window.

When the View does not attach to the current window, the value of mAttachInfo is null. Therefore, execute the else statement. Let's look at the getRunQueue () and its post () methods:

static final ThreadLocal<RunQueue> sRunQueues = new ThreadLocal<RunQueue>();    static RunQueue getRunQueue() {       RunQueue rq = sRunQueues.get();       if (rq != null) {           return rq;       }       rq = new RunQueue();       sRunQueues.set(rq);       return rq;   }   ……   static final class RunQueue {       private final ArrayList<HandlerAction> mActions = new ArrayList<HandlerAction>();         void post(Runnable action) {           postDelayed(action, 0);       }         void postDelayed(Runnable action, long delayMillis) {           HandlerAction handlerAction = new HandlerAction();           handlerAction.action = action;           handlerAction.delay = delayMillis;             synchronized (mActions) {               mActions.add(handlerAction);           }       }               void executeActions(Handler handler) {           synchronized (mActions) {               final ArrayList

In this way, the Runnable will be inserted into a static ThreadLocal RunQueue Queue (post in the working thread will insert the RunQueue queue of the working thread). For the example given at the beginning of this article, when will the inserted Runnable be executed?

You can call the runqueue.exe cuteActions () method in only one place, that is, in the following non-static methods of the ViewRootImpl class

private void performTraversals() {                if (mLayoutRequested && !mStopped) {              // Execute enqueued actions on every layout in case a view that was detached              // enqueued an action after being detached              getRunQueue().executeActions(attachInfo.mHandler);          }  }  

This method is executed in the UI thread (see ViewRootImpl. handleMessage (), so when the UI thread executes getRunQueue () in the queue mtraversals (), the RunQueue In the UI thread is obtained, in this way, RunQueue in the AsyncTask thread will never be executed, and AsyncTask is implemented by the thread pool. The threads started by AsyncTask will exist for a long time, resulting in the following reference relationship:

 

AsyncTask thread => static ThreadLocal RunQueue => Runnable => View => Activity;

So even if the activity is finished, there is always a static reference chain to reference this activity, and the Activity usually references many resources, such as parts, which eventually causes serious resource leakage.

Finally, I changed it to write

Package com. xxx. launcher. view; import android. content. context; import android. util. log; import android. view. view; public class WeatherTextView extends SkinTextView {public WeatherTextView (Context context) {super (context) ;}@ Override protected void onAttachedToWindow () {super. onAttachedToWindow (); postDelayed (mShowCityRunnable, 200); // execute the post method in the onAttachedToWindow method} @ Override protected void onWindowVisibilityChanged (int visibility) {super. onWindowVisibilityChanged (visibility); if (visibility = View. VISIBLE) {post (mShowCityRunnable) ;}@override protected void onDetachedFromWindow () {super. onDetachedFromWindow (); onCancel () ;}; public void onCancel () {removeCallbacks (callback);} private Runnable mShowCityRunnable = new Runnable () {@ Override public void run () {Log. I ("mShowCityRunnable ------- TAG", "run" + mShowCityRunnable); setText (city );}};}

The number of MainMenuActivity times, the MainMenuActivity object will only save one copy.

Ps: as to why MainMenuActivity + 1 is displayed in two Histogram (Histogram) Comparison charts, it is because this is the class name. After the class is loaded, it will not be recycled before the process ends.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

========================================================== ========================================================== ========================================================== ========

========================================================== ========================================================== ========================================================== ========

 

This vulnerability is generally caused by mStorageManager registration but not cancellation.

mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);mStorageManager.registerListener(mStoragelistener);

Cancel registration.

if (mStorageManager != null) {    mStorageManager.unregisterListener(mStoragelistener);}

 

 

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.