更新UI的四种方式分析

来源:互联网 发布:warframe重置端口 编辑:程序博客网 时间:2024/05/19 12:39
在Android开发中,更新UI有以下四种常用方式。

方式一:

Handler类的sendEmptyMessage()或sendMessage()方法。

private Handler mHandler = new Handler() {    @Override    public void handleMessage(Message msg) {if (msg.what == MSG_REFRESH) {    mTextView.setText("blog.csdn.net/ruancoder");}    }};private void refresh1() {    mHandler.sendEmptyMessage(MSG_REFRESH);}

方式二:
Handler类的post()方法。

private void refresh2() {    mHandler.post(new Runnable() {        @Override        public void run() {            mTextView.setText("blog.csdn.net/ruancoder");        }    });}

方式三:
View类的post()方法。

private void refresh3() {    mTextView.post(new Runnable() {        @Override        public void run() {            mTextView.setText("blog.csdn.net/ruancoder");        }    });}

方式四:
Activity类的runOnUiThread()方法。

private void refresh4() {    runOnUiThread(new Runnable() {        @Override        public void run() {            mTextView.setText("blog.csdn.net/ruancoder");        }    });}

先来看一下方式一sendEmptyMessage()的实现。

public final boolean sendEmptyMessage(int what){    return sendEmptyMessageDelayed(what, 0);}

再来看一下方式二Handler类的post()方法。

public final boolean post(Runnable r){    return  sendMessageDelayed(getPostMessage(r), 0);}

我们会发现,这两种方式内部都是调用了sendEmptyMessageDelayed()方法,即都是采用Handler类发送消息的方式。
接着看方式三View类的post()方法。
public boolean post(Runnable action) {    final AttachInfo attachInfo = mAttachInfo;    if (attachInfo != null) {        return attachInfo.mHandler.post(action);    }    // Assume that post will succeed later    ViewRootImpl.getRunQueue().post(action);    return true;}
其内部调用的是Handler类的post()方法,即上述方式二。


再看Activity类的runOnUiThread()方法。

public final void runOnUiThread(Runnable action) {    if (Thread.currentThread() != mUiThread) {        mHandler.post(action);    } else {        action.run();    }}
其内部调用的是也是Handler类的post()方法,即上述方式二。

可以看到,上述四种方式都会执行到sendEmptyMessageDelayed()方法。

也就是说,即使采用后三种方式,最终都会执行第一种方式的实现。即Handler发送消息,然后在Handler类的handlerMessage()中接收消息。


我们接着sendEmptyMessageDelayed()方法继续往下走。

public final boolean sendMessageDelayed(Message msg, long delayMillis){    if (delayMillis < 0) {        delayMillis = 0;    }    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(Message msg, long uptimeMillis) {    MessageQueue queue = mQueue;    if (queue == null) {        RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");        Log.w("Looper", e.getMessage(), e);        return false;    }    return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {    msg.target = this;    if (mAsynchronous) {        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);}

可以看到,最终会执行到下面两行代码。
msg.target = this;mQueue.enqueueMessage(msg, uptimeMillis);
(1).将当前发送msg的Handler对象,赋值给msg的target属性。
(2).将msg添加到消息队列mQueue。


此时,在Handler类中,我们已经无法进行接下来的执行流程了。那么最终消息是如何到达Handler类的handleMessage(Message msg)方法的呢?
下面我们来进行分析。

在Handler机制中涉及到四个重要的类,Handler、Looper、MessageQueue、Message。

Handler类中定义了成员变量mQueue和mLooper,分别是MessageQueue和Looper类型对象。

Handler类的成员变量:

public class Handler {    // other code    final MessageQueue mQueue;    final Looper mLooper;    // other code}

Handler类的构造方法:

public Handler(Callback callback, boolean async) {    // other code    mLooper = Looper.myLooper();    if (mLooper == null) {        throw new RuntimeException(            "Can't create handler inside thread that has not called Looper.prepare()");    }    mQueue = mLooper.mQueue;    // other code}

在构造方法中,Looper.myLooper()从当前线程中获取绑定的Looper对象,赋值给成员变量mLooper,再从mLooper对象中获取到mQueue对象。

Looper类的mQueue对象是何时创建的呢?
看一下Looper类的构造方法。

private Looper(boolean quitAllowed) {    mQueue = new MessageQueue(quitAllowed);    mThread = Thread.currentThread();}
当Looper对象创建时,就会创建一个MessageQueue类型对象mQueue。

接下来,我们将要关心的就是,Looper对象是在哪里创建的。

这时需要进入到ActivityThread类。
(注:ActivityThread.java文件的路径:\platform_frameworks_base\core\java\android\app\ActivityThread.java)

ActivityThread管理应用程序的主线程的执行。主线程之所以可以使用Handler进行通信,是因为主线程中已经创建了Looper。如果子线程需要使用Handler通信,需要自己去创建Looper。

来看一下ActivityThread类的main()方法。
public static void main(String[] args) {    // other code    Looper.prepareMainLooper();    Looper.loop();    // other code}

在main()方法中,调用了Looper.prepareMainLooper()和Looper.loop()两个方法。


(1).Looper.prepareMainLooper()方法

public static void prepareMainLooper() {    prepare(false);    synchronized (Looper.class) {        if (sMainLooper != null) {            throw new IllegalStateException("The main Looper has already been prepared.");        }        sMainLooper = myLooper();    }}private static void prepare(boolean quitAllowed) {   if (sThreadLocal.get() != null) {        throw new RuntimeException("Only one Looper may be created per thread");   }   sThreadLocal.set(new Looper(quitAllowed));}

在prepareMainLooper()方法中调用prepare()新建了一个looper对象,并通过threadLocal.set()方法与当前线程进行了绑定。

这里再回到Handler类的构造方法,在构造方法中是通过mLooper = Looper.myLooper()获取Looper对象。
进入Looper.myLooper()方法:
public static @Nullable Looper myLooper() {    return sThreadLocal.get();}
该方法返回的就是上面sThreadLocal通过set()添加的Looper对象。


(2).Looper.loop()方法

public static void loop() {    final Looper me = myLooper();    final MessageQueue queue = me.mQueue;    // other code    for (;;) {        Message msg = queue.next();        msg.target.dispatchMessage(msg);// other code    }    // other code}

在Looper.loop()方法中,循环从MessageQueue中获取Message对象,调用msg.target.dispatchMessage(msg)进行处理,即将msg交给发送它的Handler对象的dispatchMessage()方法。

兜了一大圈,我们又再次回到Handler类。

在Handler类的dispatchMessage()方法中,我们终于看到了熟悉的handleMessage(Message msg)方法。

/** * Handle system messages here. */public void dispatchMessage(Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}/** * Subclasses must implement this to receive messages. */public void handleMessage(Message msg) {}

到这里,我们已经明白了,通过Handler类的的sendMessage(msg)发送的消息,最终是如何执行到handleMessage(Message msg)方法中。

1 0