Android异步消息处理机制Handler
2016-08-10 23:53
399 查看
很多人第一次接触Handler可能是因为一句话”子线程不能操作ui”,那子线程能不能操作ui呢?我们在这里不多讨论(其实是可以的,但是线程不安全),我们来分析下handler是如何运转起来的。
一般用法都是在“主线程”中new一个handler
然后在子线程中sendMessage
我画了一张图简单得阐述了中间过程,可以先看一下
很显然上面得两段代码就分别是左边进去和右边出来部分,从图中野可以看出,我们接下来就应该去看下Looper这个类了。其中 prepare()和loop()是我们注意到的。
我们来看下prepare()
注释说:初始化当前线程作为一个looper。
这给了你一个机会来创建handler,在调用loop()前你必须先prepare(),而我们一般使用都没有先prepare(),所以为啥一开始我说在主线程new一个handler,因为在ActivityThread中已经帮我们建立好了一个looper(注意*内容*)
看完prepare()我们来看下loop()
其中第一行,我们可以看到
确认当前线程中是否有looper对象,如果有的话获取到当前MessageQueue的对象mQueue,其中mQueue在Looper的构造方法中就已经new好了
接下来我们看到了一个死循环
queue不断的在读取下一个消息,如果下一个消息为空则做延时操作,如果接收到消息那么调用msg.target.dispatchMessage(msg)方法将消息发送出去(msg.target这个属性我们先看为mhandler,等下提到)
,那发送到哪里了呢?上面说到dispatchMessage()是handler的方法,我们到Handler中看看
是的找到他了,他又调用了handleMessage();这个方法,那我们来看下他的实现把
空实现!!!是的这就到了我们编写的部分,我们new了handler之后要重写handleMessage方法,详见文章顶部第一段代码,到这里我们说完了Looper从preapre()到loop()再到handleMssage(),那msg是怎么从子线程发送到“主线程”的mhandler手里呢??
那我们就要来看下sendMessag()这个方法了
我们发现这几个方法到后面都是调用了sendMessageAtTime()这个方法,并却return enqueueMessage(queue, msg, uptimeMillis);,那我们来看看这个方法里面有什么
是的,你发现了,在这里 msg.target = this;他将当前handler的对象赋值给了msg的target属性,这也就是为什么前面说将msg.target看作是handler,而MessageQueue的enqueueMessage方法就是将msg放置到队列当中去!
那msg是怎么从子线程发送到“主线程”的mhandler手里呢??
我们来看下handler的构造方法
其中
并且
到此为止一个常用handler的使用处理流程就说完了!也许有理解错的地方还望大家指正!
参考博文: Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
Android Handler机制
我的博客网站:http://huyuxin.top/欢迎大家访问!评论!
一般用法都是在“主线程”中new一个handler
Handler mhandler = new Handler() { @Override public void handleMessage(Message msg) { }
然后在子线程中sendMessage
Message msg= Message.obtain(); msg.what = FLAG; msg.obj = obj; mhandler.sendMessage(msg);
我画了一张图简单得阐述了中间过程,可以先看一下
很显然上面得两段代码就分别是左边进去和右边出来部分,从图中野可以看出,我们接下来就应该去看下Looper这个类了。其中 prepare()和loop()是我们注意到的。
我们来看下prepare()
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); //在当前线程new了一个Looper对象 }
注释说:初始化当前线程作为一个looper。
这给了你一个机会来创建handler,在调用loop()前你必须先prepare(),而我们一般使用都没有先prepare(),所以为啥一开始我说在主线程new一个handler,因为在ActivityThread中已经帮我们建立好了一个looper(注意*内容*)
public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); **Looper.prepareMainLooper();** ActivityThread thread = new ActivityThread(); thread.attach(false); **Looper.loop();** if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>"; Slog.i(TAG, "Main thread of " + name + " is now exiting"); }
看完prepare()我们来看下loop()
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } }
其中第一行,我们可以看到
final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue;
确认当前线程中是否有looper对象,如果有的话获取到当前MessageQueue的对象mQueue,其中mQueue在Looper的构造方法中就已经new好了
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
接下来我们看到了一个死循环
for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } msg.target.dispatchMessage(msg); }
queue不断的在读取下一个消息,如果下一个消息为空则做延时操作,如果接收到消息那么调用msg.target.dispatchMessage(msg)方法将消息发送出去(msg.target这个属性我们先看为mhandler,等下提到)
,那发送到哪里了呢?上面说到dispatchMessage()是handler的方法,我们到Handler中看看
/** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
是的找到他了,他又调用了handleMessage();这个方法,那我们来看下他的实现把
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
空实现!!!是的这就到了我们编写的部分,我们new了handler之后要重写handleMessage方法,详见文章顶部第一段代码,到这里我们说完了Looper从preapre()到loop()再到handleMssage(),那msg是怎么从子线程发送到“主线程”的mhandler手里呢??
那我们就要来看下sendMessag()这个方法了
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
public boolean sendMessageAtTime(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); }
我们发现这几个方法到后面都是调用了sendMessageAtTime()这个方法,并却return enqueueMessage(queue, msg, uptimeMillis);,那我们来看看这个方法里面有什么
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
是的,你发现了,在这里 msg.target = this;他将当前handler的对象赋值给了msg的target属性,这也就是为什么前面说将msg.target看作是handler,而MessageQueue的enqueueMessage方法就是将msg放置到队列当中去!
那msg是怎么从子线程发送到“主线程”的mhandler手里呢??
我们来看下handler的构造方法
public Handler(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 that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
其中
mLooper = Looper.myLooper();//确保了子线程中的Looper对象来源于"主线程"
并且
mQueue = mLooper.mQueue;//确保了sendMessage()发送出去的msg是发送到主线程Looper的消息队列
到此为止一个常用handler的使用处理流程就说完了!也许有理解错的地方还望大家指正!
参考博文: Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
Android Handler机制
我的博客网站:http://huyuxin.top/欢迎大家访问!评论!
相关文章推荐
- Android 异步消息处理机制(一) 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制的妙用(二) Handler 创建强大的图片加载类
- 26、Android之Handler异步消息处理机制
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- 【 Android】handler异步消息处理机制完全解析,带你从源码的角度彻底理解
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- (4.1.21.4)Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android多线程及异步任务消息处理机制(一)--Handler的使用
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android Handler 异步消息处理机制的妙用 创建强大的图片加载类
- Android之异步处理Handler和消息机制处理
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- Android 异步消息处理机制Looper、Handler、Message三者关系
- Android异步消息处理机制 handler
- Android异步消息处理机制(一):理解 Looper、Handler、Message三者间关系