不论是sendMessage
、sendEmptyMessage
还是sendMessageDelayed
最终都会调用enqueueMessage
方法
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { //消息绑定Handler对象 msg.target = this; msg.workSourceUID = ThreadLocalWorkSource.getUID(); //消息是否异步,true标识异步 if (mAsynchronous) { msg.setAsynchronous(true); } //执行消息队列的入队方法,uptimeMillis表示消息的发送时间 return queue.enqueueMessage(msg, uptimeMillis); }
1.2 Handler在子线程发送消息在子线程创建Handler时,需在调用Looper.prepare()
和Looper.loop()
。
Looper.java 准备异步消息发送 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 是JDK中为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。这里存放的是Looper对象 sThreadLocal.set(new Looper(quitAllowed)); } //创建looper的时候,也会创建当前线程的消息队列和标记当前线程线程 private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
2 Looper取消息 public static voID loop() { //拿当前线程的looper对象 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //确保Looper.loop()调用时,保证消息队列中的消息需要执行完成 if (me.mInLoop) { Slog.w(TAG, "Loop again would have the queued messages be executed" + " before this one completed."); } me.mInLoop = true; final MessageQueue queue = me.mQueue; // 核实当前线程的身份 Binder.clearCallingIDentity(); final long IDent = Binder.clearCallingIDentity(); ... for (;;) { //开始取消息 Message msg = queue.next(); // might block if (msg == null) { //无消息的时候会退出 return; } final Observer observer = sObserver; ...//省略部分 //消息发送的开始时间 final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0; final long dispatchEnd; Object token = null; if (observer != null) { token = observer.messagedispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUID(msg.workSourceUID); try { //分发给Handler去处理该消息 msg.target.dispatchMessage(msg); if (observer != null) { observer.messagedispatched(token, msg); } dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) { if (observer != null) { observer.dispatchingThrewException(token, msg, exception); } throw exception; } finally { //线程工作的恢复 ThreadLocalWorkSource.restore(origWorkSource); } ... final long newIDent = Binder.clearCallingIDentity(); if (IDent != newIDent) { //再次校验当前线程的身份 } //释放消息 msg.recycleUnchecked(); } }
3 MessageQueue的next取消息 //取消息 for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } //仅唤醒一次 nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // 当前时间 final long Now = SystemClock.uptimeMillis(); Message prevMsg = null; //mMessages 表示当前等待处理的消息 Message msg = mMessages; if (msg != null && msg.target == null) { // 寻找下一条异步消息 do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (Now < msg.when) { // 下一条消息未准备好,这等待,此时会进入到 Binder.flushPendingCommands()这里 nextPollTimeoutMillis = (int) Math.min(msg.when - Now, Integer.MAX_VALUE); } else { //当前不是阻塞状态 mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; msg.markInUse(); return msg; } } else { //没有更多消息 不需要循环 nextPollTimeoutMillis = -1; } // 空闲的IDleHandler数量 if (pendingIDleHandlerCount < 0 && (mMessages == null || Now < mMessages.when)) { pendingIDleHandlerCount = mIDleHandlers.size(); } if (pendingIDleHandlerCount <= 0) { // 没有空闲的处理程序,循环等待更多 mBlocked = true; continue; } if (mPendingIDleHandlers == null) { mPendingIDleHandlers = new IDleHandler[Math.max(pendingIDleHandlerCount, 4)]; } mPendingIDleHandlers = mIDleHandlers.toArray(mPendingIDleHandlers); } // 运行空闲的处理程序,仅限在第一次迭代时会到达这里. for (int i = 0; i < pendingIDleHandlerCount; i++) { final IDleHandler IDler = mPendingIDleHandlers[i]; mPendingIDleHandlers[i] = null; // release the reference to the handler boolean keep = false; try { keep = IDler.queueIDle(); } catch (Throwable t) { Log.wtf(TAG, "IDleHandler threw exception", t); } if (!keep) { synchronized (this) { mIDleHandlers.remove(IDler); } } } pendingIDleHandlerCount = 0; //不影响下次下次消息的获取,保持的调用Binder.flushPendingCommands()一致。 nextPollTimeoutMillis = 0; }
HandlerThread的使用 HandlerThread handlerThread = new HandlerThread("xxx"); handlerThread.start();//Looper.prepare();不用我们再次调用 //拿到新创建的线程的looper来创建Handler Looper looper = handlerThread.getLooper(); Handler handler2 = new Handler(looper); handler2.sendMessage(Message);
小纸片记住ThreadLocal是用来区分Handler主线程MessageQueue的next()不仅你会使用,系统的异步刷新UI也会使用 总结 以上是内存溢出为你收集整理的Android之Handler全部内容,希望文章能够帮你解决Android之Handler所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)