Handler 引起的內(nèi)存泄露
先看一組簡單的代碼
- public class SampleActivity extends Activity {
 - private final Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - // ...
 - }
 - }
 - }
 
當(dāng)我們這樣寫在一個(gè)Activity中時(shí),Android Lint會(huì)提示我們這樣一個(gè)  warning: In Android, Handler classes should be static or  leaks might occur.。
意思說:在Android中,Handler  類應(yīng)該是靜態(tài)的否則可能發(fā)生泄漏。
為什么會(huì)是這樣呢?
了解一下Handler
- 當(dāng)Android程序***次創(chuàng)建的時(shí)候,在主線程同時(shí)會(huì)創(chuàng)建一個(gè)
Looper對(duì)象。Looper實(shí)現(xiàn)了一個(gè)簡單的消息隊(duì)列,一個(gè)接著一個(gè)處理Message對(duì)象。程序框架所有主要的事件(例如:屏幕上的點(diǎn)擊時(shí)間,Activity生命周期的方法等等)都包含在Message對(duì)象中,然后添加到Looper的消息隊(duì)列中,一個(gè)一個(gè)處理。主線程的Looper存在整個(gè)應(yīng)用程序的生命周期內(nèi)。 - 當(dāng)一個(gè)
Handler對(duì)象在主線程中創(chuàng)建的時(shí)候,它會(huì)關(guān)聯(lián)到Looper的 message queue 。Message添加到消息隊(duì)列中的時(shí)候Message會(huì)持有當(dāng)前Handler引用,當(dāng)Looper處理到當(dāng)前消息的時(shí)候,會(huì)調(diào)用Handler#handleMessage(Message). - 在
java中,no-static的內(nèi)部類會(huì) 隱式的 持有當(dāng)前類的一個(gè)引用。static的類則沒有。 
在什么地方引起了內(nèi)存的泄露呢?再看看下面一段代碼
- public class SampleActivity extends Activity {
 - private final Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - // ...
 - }
 - }
 - @Override
 - protected void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - // 發(fā)送一個(gè)10分鐘后執(zhí)行的一個(gè)消息
 - mHandler.postDelayed(new Runnable() {
 - @Override
 - public void run() { }
 - }, 600000);
 - // 結(jié)束當(dāng)前的Activity
 - finish();
 - }
 - }
 
當(dāng)Activity結(jié)束后,在 Message queue  處理這個(gè)Message之前,它會(huì)持續(xù)存活著。這個(gè)Message持有Handler的引用,而Handler有持有Activity(SampleActivity)的引用,這個(gè)Activity所有的資源,在這個(gè)消息處理之前都不能也不會(huì)被回收,所以發(fā)生了內(nèi)存泄露。
解決辦法,看下面一段代碼
- public class SampleActivity extends Activity {
 - /**
 - * 使用靜態(tài)的內(nèi)部類,不會(huì)持有當(dāng)前對(duì)象的引用
 - */
 - 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);
 - /**
 - * 使用靜態(tài)的內(nèi)部類,不會(huì)持有當(dāng)前對(duì)象的引用
 - */
 - private static final Runnable sRunnable = new Runnable() {
 - @Override
 - public void run() { }
 - };
 - @Override
 - protected void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - // 發(fā)送一個(gè)10分鐘后執(zhí)行的一個(gè)消息
 - mHandler.postDelayed(sRunnable, 600000);
 - // 結(jié)束
 - finish();
 - }
 - }
 
ok,結(jié)束
NOTE:  好多人有擔(dān)心弱引用的Activity回收的情況,這個(gè)完全不用擔(dān)心的,因?yàn)槲覀冊(cè)谶@個(gè)界面的時(shí)候,這個(gè)Activity  是不會(huì)被回收的,想想 如果我們的這個(gè)Activity被回收了,我們的這個(gè)界面是怎么存在的呢?
NOTE2: 各位,我是參照AsyncTask  ,查看文檔和自己的理解,存在我解釋不了的地方,還望見諒,如有錯(cuò)誤還望見諒。
NOTE3:具體怎么防止泄漏我也說不清楚,但是Handler 下面有一段源碼
- final Class<? extends Handler> klass = getClass();
 - if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
 - (klass.getModifiers() & Modifier.STATIC) == 0) {
 - Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
 - klass.getCanonicalName());
 - }
 















 
 
 







 
 
 
 