php网站培训班湖北营销网站建设联系方式
web/
2025/9/27 22:27:58/
文章来源:
php网站培训班,湖北营销网站建设联系方式,wordpress读者墙插件,免费头像在线制作为了方便阅读将文章分为使用篇和源码解析两篇#xff0c;上一篇已经写了Handler是什么、有什么、怎们用#xff0c;这一片从源码的角度分析完整流程#xff0c;看看Handler消息机制到底是啥原理。才疏学浅#xff0c;如有错误#xff0c;欢迎指正#xff0c;多谢。
完整…为了方便阅读将文章分为使用篇和源码解析两篇上一篇已经写了Handler是什么、有什么、怎们用这一片从源码的角度分析完整流程看看Handler消息机制到底是啥原理。才疏学浅如有错误欢迎指正多谢。
完整流程首先初始化Handler并new一个CallBack重写handleMessage或者run方法等着用来接收消息。 然后使用handler的sendMessage发送消息。 流程已经明确涉及文件主要有Handler、Message、MessageQueue、Looper
1.Handler 1.1 Handler类有个handleMessage方法是个空方法等后面子类重写该方法上方便我们调用方自己实现并接收参数进行处理。就是我们上一篇中3.1的方式一那个TestHandler中的handleMessage方法接收数据的回调。 1.2 Handler类内部有个接口Callback只有一个方法 boolean handleMessage(NonNull Message msg)和Handler类的handleMessage方法同名; 就是我们方式二接收数据的回调。 1.3 我们怎们能收到消息呢他其实是依赖Looper的这里先说接收消息的最后一个流程一个核心方法Handler的dispatchMessage方法消息会在dispatchMessage方法被调用时送过来它会判断msg.callback如果不为空则调用它的run()方法,为啥呢因为它不是Handler内部的CallBack接口他就是个Runnable应用场景是上一篇中的场景五; msg.callback为空则判断Handler内部的CallBack对象是否为空如果不空mCallback.handleMessage(msg))反之则调用handleMessage(msg)详见dispatchMessage方法源码.
public void dispatchMessage(NonNull Message msg) {if (msg.callback ! null) {handleCallback(msg);} else {if (mCallback ! null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}
}
2. Message Message类有个target成员变量就是handler后面也是通过这个对象回调给Handler的handleMessage的。 可能会发现我们从来没有对Message的target做过赋值的操作啊其实是源码将消息添加到仓库的时候都会将当前handler赋值给messegehandler的enqueueMessage方法将消息放入到对列前无条件赋值的不管现在是否已经有值然后调用MessageQueue的enqueueMessage方法将消息存储
handler的enqueueMessage方法
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);
}
3.MessageQueue 插入enqueueMessage方法 消息仓库MessageQueue中的enqueueMessage方法这里是一个单链表循环赋值。
boolean enqueueMessage(Message msg, long when) {if (msg.target null) {throw new IllegalArgumentException(Message must have a target.);}synchronized (this) {if (msg.isInUse()) {throw new IllegalStateException(msg This message is already in use.);}if (mQuitting) {IllegalStateException e new IllegalStateException(msg.target sending message to a Handler on a dead thread);Log.w(TAG, e.getMessage(), e);msg.recycle();return false;}msg.markInUse();msg.when when;Message p mMessages;boolean needWake;if (p null || when 0 || when p.when) {// New head, wake up the event queue if blocked.msg.next p;mMessages msg;needWake mBlocked;} else {// Inserted within the middle of the queue. Usually we dont have to wake// up the event queue unless there is a barrier at the head of the queue// and the message is the earliest asynchronous message in the queue.needWake mBlocked p.target null msg.isAsynchronous();Message prev;for (;;) {prev p;p p.next;if (p null || when p.when) {break;}if (needWake p.isAsynchronous()) {needWake false;}}msg.next p; // invariant: p prev.nextprev.next msg;}// We can assume mPtr ! 0 because mQuitting is false.if (needWake) {nativeWake(mPtr);}}return true;
}
还有一个取消息的next方法 从mMessages取消息也是工具方法由Looper来调用。代码较只截取一部分吧请自行翻阅源码查看 4.Looper 此时消息已经被添加到了MessageQueue我们看一下怎样取出来此时就要用到Looper类的loop方法代码较只截取一部分吧请自行翻阅源码查看 loop方法取消息有一个死循环调用上面提到的MessageQueue的next方法 - 取到msg为空就return终止不空则通过msg.target这个Handler调用dispatchMessage方法至此已明了 MessageQueue的next方法也有一个死循环两层死循环嵌套了; 需要调用Looper.loop()就开启了取消息模式相同的思考,我从来没有调用过那消息是怎么发给我的呢是的主线程的它同样是是在ActivityThread类的main方法里在调用Looper.prepareMainLooper();之后调用了Looper.loop();
ok穿起来了。 handler死循环不会anr是因为nativePollOnce方法当没有消息时会阻塞在这个native方法涉及Linux的pipi/epoll机制阻塞时主线程会释放CPU资源进入休眠状态知道下一个消息到达或者事物发生会通过pipe管道写入疏浚来唤醒主线程继续工作。主线程休眠和死循环区别休眠是在内核状态里主线程被挂起线程状态转移到休眠而死循环时主线程死锁在这里一直执行同一块代码无法再相应其他事件。只能确定这里native的方法死循环和咱应用层写的死循环不一样它不会使程序ANR里面具体实现原理请各位大佬自行研究。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83003.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!