更新UI的四种方式分析
来源:互联网 发布:warframe重置端口 编辑:程序博客网 时间:2024/05/19 12:39
在Android开发中,更新UI有以下四种常用方式。
方式一:
方式二:
Handler类的post()方法。
方式三:
View类的post()方法。
方式四:
Activity类的runOnUiThread()方法。
先来看一下方式一sendEmptyMessage()的实现。
可以看到,最终会执行到下面两行代码。
(2).将msg添加到消息队列mQueue。
在构造方法中,Looper.myLooper()从当前线程中获取绑定的Looper对象,赋值给成员变量mLooper,再从mLooper对象中获取到mQueue对象。
Looper类的mQueue对象是何时创建的呢?
看一下Looper类的构造方法。
接下来,我们将要关心的就是,Looper对象是在哪里创建的。
这时需要进入到ActivityThread类。
(注:ActivityThread.java文件的路径:\platform_frameworks_base\core\java\android\app\ActivityThread.java)
ActivityThread管理应用程序的主线程的执行。主线程之所以可以使用Handler进行通信,是因为主线程中已经创建了Looper。如果子线程需要使用Handler通信,需要自己去创建Looper。
来看一下ActivityThread类的main()方法。
在main()方法中,调用了Looper.prepareMainLooper()和Looper.loop()两个方法。
(1).Looper.prepareMainLooper()方法
在prepareMainLooper()方法中调用prepare()新建了一个looper对象,并通过threadLocal.set()方法与当前线程进行了绑定。
这里再回到Handler类的构造方法,在构造方法中是通过mLooper = Looper.myLooper()获取Looper对象。
进入Looper.myLooper()方法:
在Looper.loop()方法中,循环从MessageQueue中获取Message对象,调用msg.target.dispatchMessage(msg)进行处理,即将msg交给发送它的Handler对象的dispatchMessage()方法。
兜了一大圈,我们又再次回到Handler类。
在Handler类的dispatchMessage()方法中,我们终于看到了熟悉的handleMessage(Message msg)方法。
到这里,我们已经明白了,通过Handler类的的sendMessage(msg)发送的消息,最终是如何执行到handleMessage(Message msg)方法中。
方式一:
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
- 更新UI的四种方式分析
- 更新UI的四种方式
- Android更新UI的四种方式
- 更新UI的四种方式
- Android更新UI的四种方式
- android进行异步更新UI的四种方式
- Android异步更新UI的四种方式
- Android异步更新UI的四种方式
- Android异步更新UI的四种方式
- Android基础之UI更新的四种方式
- Android异步更新UI的四种方式
- Android异步更新UI的四种方式
- android进行异步更新UI的四种方式
- Android异步更新UI的四种方式
- android studio 更新ui的四种方式 handler
- handler更新UI四种方式的简单实现
- Android异步更新UI的四种方式
- android进行异步更新UI的四种方式
- 剑指offer第9题:斐波纳西数列
- poj Musical Theme 后缀数组
- 仿网易新闻的顶部导航指示器
- BestCoder Round #25
- PAT-A 1023. Have Fun with Numbers
- 更新UI的四种方式分析
- Eclipse 启动优化问题(详细)
- IOS开发 core data 简单使用和注意
- Java类装载器研究
- 博弈小结
- 北大学习总结
- 线程池的大小应该设为多少
- 设计模式-创建型-抽象工厂模式(Abstract Factory)
- 【Git/Github学习笔记】Git常用命令(代码冲突二)