Handler

Android的消息机制——Handle

1.Handle的定义、作用

    Android中如果在子线程中更新UI会出现exception,对于界面来说是不安全的;
    但是如果将耗时的操作放在主线程中,那么会导致界面加载比较耗时,对于一些加载数据耗时的操作,也会导致页面ANR(应用无响应);
    所有为了可以在子线程中进行耗时的UI操作,可以使用Handle;
    即:Handle是用来接收子线程发送的数据(消息),并且用此数据在主线程中进行UI更新;

通俗解释:
    当应用程序(Application)启动时,Android首先会开启一个主线程即UI线程,UI线程会管理页面中的UI控件,进行控件的事件分发。
    比如:点击一个button,button会有一个分发事件去响应click操作,但是如果此时需要一个耗时的操作(加载图片,读取数据等),而且将这些耗时的操作都放在主线程中话,在规定的时间内没有完成点击事件,应用会出现ANR无响应,出现错误提示强制关闭。但是如果将耗时操作放在子线程中,即在子线程中更新UI,因为子线程更新UI是不安全的,此时运行会出现异常。
    Handle可以让主线程和子线程通过Message对象来传递数据,子线程sendMessage(包含数据),Handle把这些message对象放入主线程队列中,配合主线程进行UI更新。

2.Handle机制的原理

总共分为五步:
第一步:异步通信准备
    在主线程中创建处理器对象(Looper)、消息队列对象(Message Queue)和Handle对象;
第二步:消息发送
    非UI线程通过Handle发送消息(Message)到消息队列(Message queue)中
第三步:消息循环
    消息出队:Looper循环取出消息队列(Message Queue)中的消息(Message);
    消息分发:Looper将取出的消息(Message)发送给处理者(Handle);
第四步:消息处理
    处理者(Handle)接受处理器(Looper)发送过来的消息(Message),根据消息(Message)进行UI更新操作。
在这里插入图片描述    Handler将Message发送到Looper的消息队列中,即MessageQueue,等待Looper的循环读取Message,处理Message,然后调用Message的target,即附属的Handler的dispatchMessage(),将该消息回调到handleMessage()中,然后完成更新UI操作。

3.代码示例
public class HandlerDemoActivity extends Activity {
    private static final int MESSAGE = 1;

    private Button button;

    private Handler handler = new Handler() {

        @Override
        public void handleMessage(@NonNull Message msg) {
            // 接受消息并且进行UI更新操作
            if (msg.what == MESSAGE ) {
                button.setBackgroundColor(Color.GREEN);
            }
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        button = findViewById(R.id.handler_activity_bt);

        // 子线程需要更新UI
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                    Message message = new Message();
                    message.what = MESSAGE;
                    handler.sendMessage(message);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}
Q&A

1.子线程为什么不能更新UI?
    https://www.jianshu.com/p/58c999d3ada7
2.主线程Looper.loop()里面为什么是死循环,会不会导致卡死,是不是特别消耗CPU资源?
    线程是一段可执行的代码,当可执行的代码执行完成后,线程生命周期就终止了,但是对于主线程,我们不会希望当运行一段时间就退出了,所以采用死循环才能保证它不会被退出;
只有当有需要执行的消息时,主线程才将此消息取出来执行,否则进入休眠状态,释放CPU,所以不会导致卡死或者特别消耗CPU资源。
3.handle的源码解析
    https://www.imooc.com/article/40380

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值