Android 更新UI方法的深度解析

      Android开发中,我们总是会遇到更新UI的场景。如果,我们直接在子线程中更新UI,那么会报错!提示我们,要在主线程中更新UI。那么具体更新UI有几种方法呢?下面就来列举这几种更新UI的方法。本篇是结合前面两篇文章有关Handler消息处理,如果你还没有了解,建议先看看这两篇文章,Android 源码解析Handler处理机制(一)Android 源码解析Handler处理机制(二)

1. Handler。

使用Handler更新UI,不再多说什么了,详情请看上文。

public class SecondActivity extends Activity {
    private static final int MSG_WHAT = 101;
    TextView tv;
    Button btn;
    private MyHadler mHandler1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        tv = (TextView) findViewById(R.id.tv);
        btn = (Button) findViewById(R.id.btn);
        mHandler1 = new MyHadler();
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                updateUi();
            }
        });
    }

    class MyHadler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_WHAT:
                    String str = (String) msg.obj;
                    tv.setText(str);
            }
        }
    }

    ;


    /**
     *
     */
    private void updateUi1() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message message = mHandler1.obtainMessage();
                message.what = MSG_WHAT;
                message.obj = "来自子线程的数据";
                mHandler1.sendMessage(message);
            }
        }.start();
    }
}

2.Handler的post()方法。

    private void updateUi2() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mHandler1.post(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText(" Handler.post更新UI");
                    }
                });
            }
        }.start();
    }

看看post()方法的源码,

 public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
该方法调用了sendMessageDelayed(getPostMessage(r), 0)发送一条消息,下面首先看看getPostMessage()方法,

 private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

getPostMessage()方法是将Runnable对象转化为消息对象Message的callback属性。而sendMessageDelayed()方法就不多说 了,又回到Handler的处理机制了,详情请看上文Android 源码解析Handler处理机制(二)

PS:在上文中,我们提到过Handler的dispatchMessage()方法,

  public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
可以看到,首先判断如果message的callback不等于null,则调用Handler的handleCallback()方法,否则调用Handler对象的handleMessage()方法。更加详细的描述,请看 Android 源码解析Handler处理机制(二)

3. Activity的runOnUiThread()方法。

 /**
     * 通过runOnUiThread更新UI
     */
    private void updateUi3(){
        new  Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(3*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                      tv.setText("runOnUiThread更新UI");
                  }
              });

            }
        }.start();
    }

看看runOnUiThread()方法的源码,

  public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
如果当前线程不是主线程,则调用Handler的post()方法;否则直接执行该方法。最重要的还是Handler的post()方法,相信不需要再多说什么了吧!

4.View.post(Runnable r)方法。

 private void updateUi4(){
        new Thread(){
            @Override
            public void run() {
                super.run();
                tv.post(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText("view post更新UI");
                    }
                });
            }
        }.start();
    }
再来看看post()方法的源码,

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

        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        getRunQueue().post(action);
        return true;
    }

该方法还是调用了Handler的post()方法。Handler的post()方法很重要哦!微笑(重要的事情说三遍!)有关Handler的post()方法的深度解析,详情请看,你不知道的Runnable接口,深度解析Runnable接口

PS:还可以使用AsyncTask,来请求数据以及更新UI。此处就不多说,详情请看Android 源码解析AsyncTask(一)Android 源码解析AsyncTask(二)

总结:

1.Activity的runOnUiThread()和 View.post(Runnable r)在本质上都是调用Handler的post()方法处理;

2.在子线程中直接更新UI,可以使用 Handler的post(),Activity的runOnUiThread()和 View.post(Runnable r)这三种方法。

推荐文章:Android 源码解析Handler处理机制(一)

                  Android 源码解析Handler处理机制(二)

                 你不知道的Runnable接口,深度解析Runnable接口







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值