(原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
另一方面,来看运行在main线程的handleMessage,调用它的地方是Handler的dispatchMessage,再往上推是Looper的loop方法调的handler的dispatchMessage,所以如果没猜错的话loop方法应该是main线程。
那问题来了,不是各个线程管理各自的MessageQueue吗?那运行在main线程的loop方法是怎么拿到我发到thread1的MessageQueue并处理它里边的Message的呢?
求大神解答,是我哪儿理解不对吗?

首先,Handler,Looper,MessageQueue这三者如何关联的?这里拿最简单的new 一个无参Handler为例。在创建无参的Handler时会对其中变量MessageQueue赋值,这个值就是Looper对象的MessageQueue,那么这个Looper对象又是在那创建的呢?如果是在app进程中的话,在启动该app时会调用ActivityThread,main方法进入主线程,在main函数中会有初始化Looper,并调用looper.loop()轮询MessageQueue中的Message,这个Message是handler在调用sendMessage或者post时会将Message enqueue到MessageQueue中,这样Looper 就会loop 到Handler发送到MessageQueue中的Message,loop时就会dispatchMessage了,再然后就是Hanlder处理message了,在调用sendMessage时,handler必须要重写handleMessage方法。这样就完成了发送消息和处理消息。在app的进程中,thread1还是发送消息到主线程中的MessageQueue,这个MessageQueue在首次启动app时就在创建Looper时已经创建好了。那么如果不是在app进程怎么办呢?假如是在ActivityManagerService中使用Handler的话呢?ActivityManagerService可以理解为在system_server进程中的一个线程,在启动system_server时并没有像启动一个app进程那样系统已经创建好了Looper,那么我们如果要使用Handler机制,就必须要有Handler,Looper,MessageQueue,Message,一来我们可以自己手动调用Looper.prepare和Looper.loop,另外,系统也已经封装好了,就是HandlerThread。HandlerThread是一个Thread,在里面已经将Looper,MessageQueue准备好了,这时候创建Handler时,将HandlerThread的Looper传给Handler就行了,这样Handler,Looper,MessageQueue就都有了,就可以利用Handler机制进行线程间通信了。

1.主线程是 有且仅有一个Looper对象, Looper对象里又有一个MessageQueue。
2. Looper 负责不停的loop,并调用Handler的handleMessage处理Message。
3. Handler 负责投递message, 以及提供处理消息的方法handleMessage。
4 任何非主线程, 想要给 主线程发message, 必须通过handler(该handler内部包含了主线程的Looper引用)
扩展下:
不只是涉及主线程, 任意 子线程之间要传递异步消息的话,也可以用handler, 该handler中引用的looper对象是属于那个线程的, 就会把消息投递给该线程, 并在该线程里执行 handleMessage方法。
请参考 Handler的几个构造方法。

由于Handler是在主线程中new的,而Handler的构造函数中才给其成员变量mLooper赋的值:mLooper = Looper.myLooper();所以说在子线程中send的Message其实也是发到了main线程
例如mainHandler.sendEmptyMessage(0)这个函数,他入队消息的队列是mainHandler对应的MessageQueue中,跟调用发送消息的队列无关。
(原)Android在子线程用handler发送的消息,主线程是怎么loop到的?的更多相关文章
- 【Java面试题】30 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。
题目如下: 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次, 接着再回到主线程又循环100,如此循环50次 思路如下: 子线程语主线程为互斥,可用SYNCHRONIZED.很容易想 ...
- Java线程——线程习题(一)子线程执行10次后,主线程再运行5次,这样交替执行三遍
题目:子线程执行10次后,主线程再运行5次,这样交替执行三遍 代码如下: package com.itheima.gan; /** * 子线程执行10次后,主线程再运行5次,这样交替执行三遍 * @a ...
- C#子线程执行完后,调用主线程的方法
private delegate void CheckVersionNumber_CallBack(string str);//定义一个为委托 用于 检测版本 //检测版本private void m ...
- Android开发——子线程操作UI的几种方法
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 在看方法之前需要了解一下Android中的消息机制. 转载请标明出处:h ...
- Android通过子线程更新UI的几种方式
一般情况下,UI的更新都少不了Handler,首先我们先了解一下Handler机制: Handler消息机制 定义 Message 线程间通信的数据单元,可通过message携带需要的数据创建对象:M ...
- Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载
效果图: 1.activity_main.xml 描述:定义了六个按钮 <?xml version="1.0" encoding="utf-8"?> ...
- Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别?
一个帖子的整理: Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别如果你不带参数的实例化:Handler ...
- Android子线程创建Handler方法
如果我们想在子线程上创建Handler,通过直接new的出来是会报异常的比如: new Thread(new Runnable() { public void run() { Handler hand ...
- android基础---->子线程更新UI
和许多其他的GUI 库一样,Android 的UI 也是线程不安全的.也就是说,如果想要更新应用程序里的UI 元素,则必须在主线程中进行,否则就会出现异常.了解AsyncTask的用法,请参见我的博客 ...
随机推荐
- [FFT/NTT/MTT]总结
最近重新学了下卷积,简单总结一下,不涉及细节内容: 1.FFT 朴素求法:$Coefficient-O(n^2)-CoefficientResult$ FFT:$Coefficient-O(nlogn ...
- 洛谷.4897.[模板]最小割树(Dinic)
题目链接 最小割树模板.具体见:https://www.cnblogs.com/SovietPower/p/9734013.html. ISAP不知为啥T成0分了.. Dinic: //1566ms ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- C++ 友元函数总结
1.为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率 具体来说:为了使其他类的成员函数直接访问该类的私有变量 即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同 ...
- git 创建SSH key
可以自己搭建一台运行Git的服务器,不过现阶段,为了学Git先搭个服务器绝对是小题大作.好在这个世界上有个叫GitHub的神奇的网站,从名字就可以看出,这个网站就是提供Git仓库托管服务的,所以,只要 ...
- JUnit accuracy/failure/stress test区别
accuracy test(结果准确性测试) 例如,Assert.assertEquals(expected, actual). 如果结果不符合期望则产生failure.说明程序逻辑有问题. fail ...
- Java中使用Timer和TimerTask实现多线程
转自:http://www.bdqn.cn/news/201305/9303.shtml 摘要:Timer是一种线程设施,用于安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行,可以 ...
- QThreadPool&QRunnable&类函数的使用
QThreadPool+QRunnable线程池与QThread线程两种方式使用的场景不同,QThreadPool+QRunnable线程池主要用于那种不需要一直运行的任务,而QThread主要用于长 ...
- ProxySQL
ProxySQL http://www.proxysql.com/
- Android 编程下 WebView 加载一个网页如何得到网页的 Cookie 值
http://www.cnblogs.com/sunzn/archive/2013/04/03/2998113.html mWebView.setWebViewClient(new MyWebView ...