- 总结
update: 6/21/2021
总结
由于工作线程与主线程共享地址空间,即Handler实例对象 mHandler位于线程间共享的内存堆上,工作线程与主线程都能直接使用该对象,只需要注意多线程的同步问题。
工作线程通过 mHandler 向其成员变量 MessageQueue 中添加新 Message,主线程一直处于 loop() 方法内,当收到新的 Message 时按照一定规则分发给相应的 handleMessage() 方法来处理。
所以说,Handler 消息机制用于同进程的线程间通信,其核心是线程间共享内存空间,而不同进程拥有不同的地址空间,也就不能用 handler 来实现进程间通信。

图解:
-
Handler 通过sendMessage() 发送Message 到MessageQueue 队列; -
Looper 通过loop(),不断提取出达到触发条件的Message,并将Message 交给target 来处理; - 经过
dispatchMessage() 后,交回给Handler 的handleMessage() 来进行相应地处理。 - 将
Message 加入MessageQueue 时,处往管道写入字符,可以会唤醒loop 线程;如果MessageQueue 中没有Message,并处于Idle 状态,则会执行IdelHandler 接口中的方法,往往用于做一些清理性地工作。
下面是以前的理解,看的脑壳痛,其实一句话:由于工作线程与主线程共享地址空间,即Handler实例对象 mHandler位于线程间共享的内存堆上,工作线程与主线程都能直接使用该对象
例如现在有A、B两个线程,在A线程中有创建了handler,然后在B线程中调用handler发送一个message。
- 当在A线程中创建handler的时候,同时创建了
MessageQueue 与Looper
- 你在子线程向主线程发消息,这个
mMainHandler 是在主线程初始化的,意思是用了主线程的Looper.loop(),Looper 在主线程中调用loop 进入一个无限的for 循环从MessageQueue 中取消息
- 子线程调用
mMainHandler 发送一个message
- 通过
msg.target.dispatchMessage(msg) 将message 插入到mMainHandler 对应的MessageQueue 中
-
Looper 发现有message 插入到MessageQueue 中,便取出message 执行相应的逻辑
- 因为
Looper.loop()是在主线程中启动的,所以则回到了主线程中,达到了切换线程的目的
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
private Handler mThreadHandler;
private Handler mMainHandler = new Handler(new Handler.Callback() {
// 主线程接收到子线程发送的消息
@Override
public boolean handleMessage(Message msg) {
if (msg.obj != null) {
Log.e(TAG, msg.obj.toString());
mThreadReplyText.setText("收到子线程回复:" + msg.obj.toString());
}
return true;
}
});
private EditText mMainEditText;
private TextView mThreadReplyText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainEditText = findViewById(R.id.main_edit_text);
mThreadReplyText = findViewById(R.id.thread_reply_text);
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mThreadHandler = new Handler(new Handler.Callback() {
// 子线程接收到主线程发送的消息并回复
@Override
public boolean handleMessage(Message msg) {
if (msg.obj != null) {
Message reply = Message.obtain();
reply.obj = "主线程说\"" + msg.obj.toString()+"\"";
// 在子线程中使用主线程中的Handler对象的引用向主线程发送消息
mMainHandler.sendMessage(reply);
}
return true;
}
});
Looper.loop();
}
}).start();
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.main_send_button:
Message message = Message.obtain();
message.obj = mMainEditText.getText();
// 主线程向子线程发送消息:在主线程中使用子线程中的Handler对象的引用向子线程发送消息
if (mThreadHandler != null) {
mThreadHandler.sendMessage(message);
} else {
while (mThreadHandler == null) {
Log.e(TAG, "子线程还没有完成ThreadHandler的创建");
if (mThreadHandler != null) {
Log.e(TAG, "ThreadHandler创建完成!");
mThreadHandler.sendMessage(message);
}
}
}
break;
}
}
}











