Android 更新UI方法的深度解析

来源:互联网 发布:淘宝网店进销存 编辑:程序博客网 时间:2024/04/28 03:44

      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接口。







1 0
原创粉丝点击