Handler 如何实现线程间切换


update: 6/21/2021

总结

由于工作线程与主线程共享地址空间,即Handler实例对象 mHandler位于线程间共享的内存堆上,工作线程与主线程都能直接使用该对象,只需要注意多线程的同步问题。

工作线程通过 mHandler 向其成员变量 MessageQueue 中添加新 Message,主线程一直处于 loop() 方法内,当收到新的 Message 时按照一定规则分发给相应的 handleMessage() 方法来处理。

所以说,Handler 消息机制用于同进程的线程间通信,其核心是线程间共享内存空间,而不同进程拥有不同的地址空间,也就不能用 handler 来实现进程间通信。

在这里插入图片描述

图解:

  • Handler 通过 sendMessage() 发送 MessageMessageQueue 队列;
  • Looper 通过 loop(),不断提取出达到触发条件的 Message,并将 Message 交给 target 来处理;
  • 经过 dispatchMessage() 后,交回给 HandlerhandleMessage() 来进行相应地处理。
  • Message 加入 MessageQueue 时,处往管道写入字符,可以会唤醒 loop 线程;如果 MessageQueue 中没有 Message,并处于 Idle 状态,则会执行 IdelHandler 接口中的方法,往往用于做一些清理性地工作。

下面是以前的理解,看的脑壳痛,其实一句话:由于工作线程与主线程共享地址空间,即Handler实例对象 mHandler位于线程间共享的内存堆上,工作线程与主线程都能直接使用该对象

例如现在有A、B两个线程,在A线程中有创建了handler,然后在B线程中调用handler发送一个message。

  • 当在A线程中创建handler的时候,同时创建了MessageQueueLooper
    • 你在子线程向主线程发消息,这个 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;
        }
    }
}

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值