【达内课程】线程中Handler与Looper

文章目录

概念介绍

【消息机制中的角色】
Message:消息的载体,用于封装消息的相关数据
Handler:消息的发送者与处理者,用于发送消息,并处理消息
MessageQueue:(在编程时不会使用到)消息队列,若干个消息的容器
Looper:轮询者,从消息队列中获取数据,并交给运行在主线程的 Handler 进行处理

xml
xml中增加一个按钮来发送消息

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_send_msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发出消息" />

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button btnSendMsg;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnSendMsg = findViewById(R.id.btn_send_msg);
        btnSendMsg.setOnClickListener(this);
        handler = new Handler(new InnerHandlerCallback());
    }

    @Override
    public void onClick(View view) {
        //发出消息
        Message msg = Message.obtain(handler);
        msg.sendToTarget();
        Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
    }

    private class InnerHandlerCallback implements Handler.Callback {

        @Override
        public boolean handleMessage(Message message) {
            Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " InnerHandlerCallback handleMessage()->handle message");
            return false;
        }
    }
}

运行程序,查看日志,从日志可以看出 Handler 是运行在主线程的
在这里插入图片描述
现在修改 onClick 中代码,把发送消息放在子线程中

@Override
    public void onClick(View view) {
        new Thread() {
            @Override
            public void run() {
                //发出消息
                Message msg = Message.obtain(handler);
                msg.sendToTarget();
                Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
            }
        }.start();
    }

运行程序,查看日志,可以看到发消息在子线程,处理消息还是在主线程
在这里插入图片描述
如果把创建 Handler 也放在子线程中

@Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                handler = new Handler(new InnerHandlerCallback());
                Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onCreate()->sub thread->new Handler");
                Looper.loop();
            }
        }.start();
    }

运行程序,观察日志,会发现 handle message 是同一个线程:
在这里插入图片描述
【Handler与Looper】
Handler 运行在哪个线程(在哪个线程上处理消息),取决于创建 Handler 时,关联到哪个线程上的 Looper,如果没有显示指定 Looper,则关联到当前线程

【小结】
1、在主线程创建的 Handler 对象,是运行在主线程的,所以可以直接更新 UI
2、在子线程中创建 Handler 之前,必须调用 Looper.prepare()以初始化运行在子线程中的 Looper
3、在子线程中的 Looper 必须显式的调用 Looper.loop()方法,才会开始轮询消息队列
4、在主线程中,默认就已经存在处于轮循工作状态的 Looper,而子线程中没有
5、如果没有可用的 Looper,则无法创建 Handler
6、创建 Handler 时,会默认关联当前线程上的 Looper

MessageQueue 是消息队列的意思,它主要用于存放所有通过 Handler 发送的消息。 这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue 对象

Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop()方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()方法中。每个线程中也只会有一个 Looper 对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值