Handler的经典用法里,Handler对象作为成员变量被UI界面(Activity, Fragment...)引用,所以只要工作线程里有Handler的引用或者主线程的Looper里有Message对Handler的引用,UI界面对象就不能被GC。
如果想要通过在UI界面关闭时,结束工作线程来释放工作线程对handler的引用,就要解决在主线程结束工作线程的问题。根据工作线程的内容不同,解决方式有标志位,interrupt两种,但都只能适合特定场景,具体方法本文先不做叙述。
本文不是介绍通过释放工作线程对Handler对象的引用的方式,来达到退出UI界面后,GC机制就可以立即回收UI界面对象的目的。至于主线程的Looper里持有的Message对Handler的引用,只需要在主界面退出时调用Handler的removeCallbacksAndMessages(null)即可。
本文主要是通过把Handler设置成类的静态成员变量,来避免UI界面对Handler的引用,UI界面类维护一个静态的HashMap来维护Handler的生命周期,用UI界面的具体对象的hashcode来作为在HashMap里的key。
public class MainActivity extends AppCompatActivity { private static MyHandler myHandler; private static HashMap<Integer, MyHandler> mHandlerMap = new HashMap();//当此activity有多个实例时,需要利用map容器保存静态引用的handler实例 private Thread mWorkThread;//工作线程 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myHandler = new MyHandler(this); mHandlerMap.put(this.hashCode(), myHandler); loadData(); } private void loadData() { mWorkThread = new Thread(new Runnable() { @Override public void run() { MyHandler handler = mHandlerMap.get(this.hashCode()); handler.sendMessage(handler.obtainMessage(1)); } }); } @Override protected void onDestroy() { mWorkThread.interrupt();//停掉工作线程 mHandlerMap.get(this.hashCode()).removeCallbacksAndMessages(null);//清除Looper里的message mHandlerMap.remove(this.hashCode()); myHandler = null; super.onDestroy(); } private static class MyHandler extends Handler { private WeakReference<MainActivity> mainActivityWeakReference; public MyHandler(MainActivity mainActivity) { mainActivityWeakReference = new WeakReference<>(mainActivity); } @Override public void handleMessage(Message msg) { MainActivity mainActivity = mainActivityWeakReference.get(); if (mainActivity == null) { return; } switch (msg.what) { case 1: Log.d("Tag", "msg is processing"); break; default: } } } }