Android异步更新UI的四种方法及源码简析

异步更新UI的四种方法

  • Handler.sendMessage(Message)
  • Handler.post(Runnable)
  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)

源码简析

第一种:Handler.sendMessage() (推荐)
在主线程定义

private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            mTv1.setText("这是Handler发送的Message");
        }
    };

发送消息

private void btn2Click() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message = mHandler.obtainMessage();
                mHandler.sendMessage(message);
            }
        }).start();
    }

处理消息

private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            mTv1.setText("这是Handler发送的Message");
        }
    };

Handler机制在Android中使用比较频繁,像Activity的生命周期都是通过Handler机制进行回调的.
详细源码可参看:Hanlder、Looper、MessageQueue源码解析

第二种:Handler.post() (推荐)
这是Handler.sendMessage()发送消息的另一种写法,更简洁

private void btn2Click() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mBtn2.setText("这是Handler的post");
                    }
                });
            }
        }).start();
    }

这种方法是把Runnable任务封装到Message中,通过Handler再把消息发送到消息队列,通过Looper对消息队列进行循环,再把消息发送给Handler进行UI的更新.
详细源码可参看:Hanlder、Looper、MessageQueue源码解析

第三种:Activity.runOnUiThread() (推荐)
如果在Activity中,可以使用更简洁的runOnUiThread更新代码,不用创建Handler对象

private void btn2Click() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mBtn1.setText("这是runnUiThread");
                    }
                });
            }
        }).start();
    }

Activity.runOnUiThread源码

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }

runOnUiThread()方法是属于Activity的,所以只能在Activity中调用
首先判断是否在UI线程

  • 如果不在UI线程,则和第二种一样,调用Handler.post方法更新UI
  • 如果在UI线程,则直接调用Runnable任务的run方法更新UI

第四种:View.post() (强力不推荐)
如果有子view或自定义view,处理逻辑后可以直接用view.post()方法

private void btn2Click() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                mBtn2.post(new Runnable() {
                    @Override
                    public void run() {
                        mTv1.setText("这是View的post");
                    }
                });
            }
        }).start();
    }

View.post源码

public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }

        getRunQueue().post(action);
        return true;
    }

当AttachInfo对象不为空时,也是调用Handler.post()方法更新UI
不推荐原因

  • 在api24(不包括)以下,可通过View.post()方法更新UI
  • 在Android 7.0 api24,Android 8.0 api25的手机上如果通过new创建的View,如果没有将它通过addView()加入到ViewGroup布局中,那通过View.post()将无法更新UI

总结
通过源码得知,四种方法其实归根结底都是在使用Handler机制更新UI。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值