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;
}
}
}