Android(安卓)Handler那些事儿(一)——是什么,有什么用?
Handler是什么?有什么用?
Android定义的一套同进程中线程间的消息传递机制
通常用来把子线程中的UI更新消息,传递给主线程更新UI;当然也可以反过来使用,只是会麻烦一些。
Handler消息机制是由一组MessageQueue、Message、Looper、Handler共同组成的。
如果说Binder/socket是android必须掌握的IPC机制,那么Handler则是必须掌握的消息机制。
子线程使用Handler例子
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); // Step 1: 创建Handler mHandler = new Handler() { public void handleMessage(Message msg) { //处理即将发送过来的消息 System.out.println("thread id="+Thread.currentThread().getId()); } }; Looper.loop(); }}// Step 2: 创建并启动LooperThread线程,内部包含LooperLooperThread looperThread = new LooperThread();looperThread.start();// Step 3: 发送消息looperThread.mHandler.sendEmptyMessage(10);
可以看到,在子线程中使用Handler比在主线程中使用多了Looper.prepare();和Looper.loop();的步骤。这个之后在其他文章中叙述。
拓展问题:必须是Handler吗?还有哪些方式?
首先我们来看看经常用的有哪些异步方式。
- 1、runOnUiThread
- 2、View.post
- 3、AsyncTask
1、Activity.runOnUiThread(Runnable)
Activity.java
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
看来还是Handler,如果是主线程则马上执行Run方法,如果不是继续看Handler的代码
public final boolean post(@NonNull Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } public final boolean postDelayed(@NonNull Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); }
postDelayed我们经常用,和post都是调用的sendMessageDelayed方法,只是延时为0而已
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis); } private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { msg.target = this; msg.workSourceUid = ThreadLocalWorkSource.getUid(); if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
注意SystemClock.uptimeMillis()是开机到现在的时间
enqueue就是入队嘛
public Handler(@Nullable Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { 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()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
注意这个mQueue成员变量是在Handler构造函数中初始化的,从Looper来的
2、View.post(Runnable)
View.java
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Postpone the runnable until we know on which thread it needs to run. // Assume that the runnable will be successfully placed after attach. getRunQueue().post(action); return true; } public boolean postDelayed(Runnable action, long delayMillis) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.postDelayed(action, delayMillis); } // Postpone the runnable until we know on which thread it needs to run. // Assume that the runnable will be successfully placed after attach. getRunQueue().postDelayed(action, delayMillis); return true; }
可以看到View的post和postDelayed的方法都是走的一样的路子,也看到了Handler的出现,但是第二条路 简单地说一下吧,细节不在这儿一一贴出了。我们使用 View.post() 时,其实内部它自己分了两种情况处理,当 View 还没有 attachedToWindow 时,通过 View.post(Runnable) 传进来的 Runnable 操作都先被缓存在 HandlerActionQueue,然后等 View 的 dispatchAttachedToWindow() 被调用时,就通过 mAttachInfo.mHandler 来执行这些被缓存起来的 Runnable 操作。从这以后到 View 被 detachedFromWindow 这段期间,如果再次调用 View.post(Runnable) 的话,那么这些 Runnable 不用再缓存了,而是直接交给 mAttachInfo.mHanlder 来执行。
3、AsyncTask
AsyncTask是一个轻量级的异步实现,可以轻松实现工作线程和UI线程的通信
他实现的原理也是 线程池 + Handler 具体怎么实现的去找源码吧
总结
到这儿我们发现好像这些异步类\方法只要涉及到了与主线程做通信,都使用了Handler,这就可以回答刚才的拓展问题了,他是Android设计之初就封装的一套消息传递机制,不用它还真不行。
更多相关文章
- 浅析Android中的消息机制-解决:Only the original thread that cr
- Android异步消息机制之Handler
- Android的Handler机制详解3_Looper.looper()不会卡死主线程
- Android之Handler用法总结
- Android开发之消息处理机制(一)——Handler
- Android异步加载图像小结 (含线程池,缓存方法)
- android 面试题集
- Titanium 使用刘明星的Jpush module做android端的消息推送
- [Innost]Android深入浅出之Binder机制