Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android App 內存洩露之Thread

Android App 內存洩露之Thread

編輯:關於Android編程

Thread 內存洩露

線程也是造成內存洩露的一個重要的源頭。線程產生內存洩露的主要原因在於線程生命周期的不可控。

1.看一下下面是否存在問題

 	/**
	 * 
	 * @version 1.0.0 
	 * @author Abay Zhuang 
* Create at 2014-7-17 */ public class ThreadActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyThread().start(); } private class MyThread extends Thread { @Override public void run() { super.run(); dosomthing(); } } private void dosomthing(){ } }




這段代碼很平常也很簡單,是我們經常使用的形式。

真的沒有問題嗎

我們思考一個問題:假設MyThread的run函數是一個很費時的操作,當我們開啟該線程後,將設備的橫屏變為了豎屏,
一般情況下當屏幕轉換時會重新創建Activity,按照我們的想法,老的Activity應該會被銷毀才對,然而事實上並非如此。
由於我們的線程是Activity的內部類,所以MyThread中保存了Activity的一個引用,當MyThread的run函數沒有結束時,
MyThread是不會被銷毀的,因此它所引用的老的Activity也不會被銷毀,因此就出現了內存洩露的問題。   

2.這種線程導致的內存洩露問題應該如何解決呢?

  • 第一、將線程的內部類,改為靜態內部類。
  • 第二、在線程內部采用弱引用保存Context引用。 代碼如下:

    		/**
    		 * 
    		 * @version 1.0.0
    		 * @author Abay Zhuang 
    * Create at 2014-7-17 */ public class ThreadAvoidActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyThread(this).start(); } private void dosomthing() { } private static class MyThread extends Thread { WeakReference mThreadActivityRef; public MyThread(ThreadAvoidActivity activity) { mThreadActivityRef = new WeakReference( activity); } @Override public void run() { super.run(); if (mThreadActivityRef == null) return; if (mThreadActivityRef.get() != null) mThreadActivityRef.get().dosomthing(); // dosomthing } } }


    
    
    
    
    

    上面的兩個步驟其實是切換兩個對象的雙向強引用鏈接

    1. 靜態內部類:切斷Activity 對於 MyThread的強引用。
    2. 弱引用: 切斷MyThread對於Activity 的強引用。

      3.AsynTask 內部類會如何呢?

      有些人喜歡用Android提供的AsyncTask,但事實上AsyncTask的問題更加嚴重,
      Thread只有在run函數不結束時才出現這種內存洩露問題,然而AsyncTask內部的實現機制是運用了ThreadPoolExcutor,
      該類產生的Thread對象的生命周期是不確定的,是應用程序無法控制的,
      因此如果AsyncTask作為Activity的內部類,就更容易出現內存洩露的問題。
      

      代碼如下:

      /**
       * 
       * 弱引用
       * @version 1.0.0 
       * @author Abay Zhuang 
      * Create at 2014-7-17 */ public abstract class WeakAsyncTask extends AsyncTask { protected WeakReference mTarget; public WeakAsyncTask(WeakTarget target) { mTarget = new WeakReference(target); } @Override protected final void onPreExecute() { final WeakTarget target = mTarget.get(); if (target != null) { this.onPreExecute(target); } } @Override protected final Result doInBackground(Params... params) { final WeakTarget target = mTarget.get(); if (target != null) { return this.doInBackground(target, params); } else { return null; } } @Override protected final void onPostExecute(Result result) { final WeakTarget target = mTarget.get(); if (target != null) { this.onPostExecute(target, result); } } protected void onPreExecute(WeakTarget target) { // Nodefaultaction } protected abstract Result doInBackground(WeakTarget target, Params... params); protected void onPostExecute(WeakTarget target, Result result) { // Nodefaultaction } }


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved