Handler一、简介Handler是用来结合线程的消息队列来发送、处理“Message对象”和“Runnable对象”的工具。每一个Handler实例之后会关联一个线程和该线程的消息队列。当你创建一个Handler的时候,从这时开始,它就会自动关联到所在的线程/消息队列,然后它就会陆续把Message/Runnalbe分发到消息队列,并在它们出队的时候处理掉。简单说,它是一套 Android 消息传递机制。二、用途延时操作。推送未来某个时间点将要执行的Message或者Runnable到消息队列;线程之间的通讯。将消息推送到相应线程的消息队列中,等待处理。三、使用方法(1)sendMessage// ************ 不配合线程使用 *************// 获取一个Message对象,设置what为1Message msg = Message.obtain();msg.obj = data;msg.what = IS_FINISH;mHandler.sendMessage(msg);// 接受并处理mHandler = new Handler() { @Override public void handleMessage(Message msg) { tx.setText(msg.what + “”); }}; // ************ 配合线程使用 ************* private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1) { Toast.makeText(MainActivity.this, “刷新UI、”, Toast.LENGTH_SHORT).show(); } } }; new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); mHandler.sendEmptyMessage(1); } catch (InterruptedException e) { e.printStackTrace(); } }}).start();常用 API:boolean sendMessage (Message msg) : 发送消息。boolean sendEmptyMessage (int what) : 直接拿到一个空的消息,并赋值what,然后发送到MessageQueue。boolean sendMessageDelayed (Message msg, long delayMillis) : 在延迟delayMillis毫秒之后发送一个Message。boolean sendMessageAtTime (Message msg, long uptimeMillis) : 在某个时间点执发送消息。void removeMessages (int what) : 移除所有what值得Message对象。(2)post// ************ 不配合线程使用 **********private Handler mHandler = new Handler();handler.post(new Runnable() { @Override public void run() { tvMessage.setText(“使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。”); }}); // ************ 配合线程使用 ************* new Thread(new Runnable() { @Override public void run() { // 在子线程中实例化Handler同样是可以的,只要在构造函数的参数中传入主线程的Looper即可 Handler handler = new Handler(Looper.getMainLooper()); // 通过Handler的post Runnable到UI线程的MessageQueue中去即可 handler.post(new Runnable() { @Override public void run() { // 在MessageQueue出队该Runnable时进行的操作 tvMessage.setText(“使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。”); } }); }}).start();常用 API:boolean post (Runnable r) : 将Runnable对象加入MessageQueue。boolean postAtTime (Runnable r, Object token, long uptimeMillis) : 在某个时间点执行Runnable r。boolean postDelayed (Runnable r, long delayMillis) : 当前时间延迟delayMillis个毫秒后执行Runnable r。void removeCallbacks (Runnable r, Object token) : 移除MessageQueue中的所有Runnable对象。void removeCallbacksAndMessages (Object token) : 移除MessageQueue中的所有Runnable和Message对象。四、原理Handler 的初始化,其实是初始化 Looper 和 MessageQueue。通过 Looper.Prepare 实例化 Looper 和 MessageQueue ,并将 Looper 设置进 ThreadLocal(所以,使用 Handler 之前一定要调用 Looper.Prepare)。ThreadLocal.set 方法的作用是将设置的值(这里是当前初始化的 Looper)与当前线程进行绑定(当前线程就是调用 Looper.prepare 的线程)。主线程中没有显式的调用 Looper.Prepare 是因为,Android 系统已经帮我们调用了 Looper.Prepare。Handler 在调用 sendMessage 的时候主要做了两件事:1.将自己设置给 Message 的 Target 变量,从而将 Handler 与 Message 绑定在一起;2.将 Message 放入 MessageQueue 队列中。Looper.loop 从 MQ 中轮训获取消息,消息不为 Null 则回调 disPatchMessage 方法(Runnable 对象 OR handlerMessage)。总结:Handler : 负责发送和处理消息。Message : 用来携带需要的数据。MessageQueue : 消息队列,用来存储 Message 的。Looper : 消息轮巡器,负责不停的从 MessageQueue 中取 Message。子线程中使用 Handler:class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); }}五、Handler 引发的内存泄漏外部类Activity中定义了一个非静态内部类Handler,非静态内部类默认持有对外部类的引用。如果外部Activity突然关闭了,但是MessageQueue中的消息还没处理完,那么Handler就会一直持有对外部Activty的引用,垃圾回收器无法回收Activity,从而导致内存泄漏。解决方法:1.停掉线程(切断了与 Activity 之间的关联)或移除 removexxx 消息;2.将Handler声明为静态类。改成静态内部类后,对外部类的引用设为弱引用,在垃圾回收时,会自动将弱引用的对象回收。如:public class HandlerActivity extends AppCompatActivity { private final MyHandler mHandler = new MyHandler(this); private static final Runnable mRunnable = new Runnable() { @Override public void run() { // 操作 } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fourth); mHandler.postDelayed(mRunnable, 100010); finish(); } private static class MyHandler extends Handler { WeakReference<HandlerActivity> mWeakActivity; public MyHandler(HandlerActivity activity) { this.mWeakActivity = new WeakReference<HandlerActivity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); final HandlerActivity mActivity = mWeakActivity.get(); if (mActivity != null) { // 处理消息 } } }}六、HandlerThreadHandlerThread 是一种线程,它和普通的 Thread 之间的区别就是 HandlerThread 在创建的时候会提供自己该线程的 Looper 对象,不需要手动创建 Looper。HandlerThread handlerThread = new HandlerThread(“downloadImage”); // 当前线程的名字,可以任意字符串handlerThread.start(); // 必须先开启线程 / * 该callback运行于子线程 */class ChildCallback implements Handler.Callback { @Override public boolean handleMessage(Message msg) { // 在子线程中进行相应的网络请求 // 通知主线程去更新UI mUIHandler.sendMessage(msg1); return false; }}Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());final HandlerThread downloadAThread = new HandlerThread(“downloadAThread”);downloadAThread.start();Handler downloadAHandler = new Handler(downloadAThread.getLooper());// downloadAHandler 子线程的 HandlerdownloadAHandler.postDelayed(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), “下载A完成”, Toast.LENGTH_SHORT).show(); mainHandler.post(new Runnable() { @Override public void run() { tv_A.setText(“A任务已经下载完成”); } }); }}, 1000 * 5);当我们不需要HandlerThread的时候,我们可以调用quitSafely()或者quit()方法来结束这个线程。参考文章:Android基础夯实–你了解Handler有多少?,Android面试常客之Handler全解