作用
子线程执行完要更新UI的时候,我们又必须回到主线程来更新,实现这一功能常用的方法是执行 Activity的runOnUiThread()方法
使用方式
runOnUiThread(new Runnable() {
@Override
public void run() {//放更新ui的代码
if (adapter != null && bluetoothLeDeviceStore != null) {
adapter.setListAll(bluetoothLeDeviceStore.getDeviceList());
updateItemCount(adapter.getCount());
}
}
});
源码部分
final Handler mHandler = new Handler();
private Thread mUiThread;
// ...
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
// ...
}
源码分析
调用的时候判断是否是在主线程上,如果是主线程上直接将执行Runnable接口的run方法,如果不是主线程话,调用mHandler.post(action);将Runnable添加到主线程的消息队列上。注释1 因为使用空构造方法,此时指向当前线程的Looper。当mHandler调用post的时候就会将Runnable放进注释2消息队列中。
Handler
Handler是处理机制,它会将数据放入到looper的消息队列中,当到了执行时,它负责在looper绑定的线程执行这个消息
1. 在构造方法中指定Looper:
Handler handler = new Handler(Looper looper);
2. 使用空构造方法,此时指向当前线程的Looper:注释1
Handler handler = new Handler();
Handler能非常便利的创建消息并将其添加到Looper的消息队列末尾,如post()。 注释2
private Handler mHandle;
mHandle.post(new Runnable() {
@Override
public void run() {
}
});
Looper
Looper字面意思就是“循环”,保持线程存活。
在没使用Looper时候,如果我们为了减小内存而不创建新的线程来复用
这个线程的时候,我们需要它保持存活并等待新的指令。常见的做法是创建一个循环,实现如下图
public class MyThread extends Thread {
private boolean running;
@Override
public void run() {
while (running) {
// do something...
}
}
}
只要while循环没执行完,线程就保持存活。
关于Looper值得一提的事:
* 线程默认不会得到Looper;
* 可以再线程中创建一个Looper;
* 每个线程只能创建一个Looper。
下面我们用Looper替换white循环:
public class MyThread extends Thread {
@Override
public void run() {
Looper.prepare();
Looper.loop();
}
}
调用Looper.prepare()检查当前线程中是否有Looper,如果没有则创建。调用Looper.loop()后Looper开始循环。
这样,Looper循环并保持线程存活,但这样什么也不做的线程存活是没有意义的。
当创建Looper时,它创建了一个消息队列(MessageQueue),用来存放消息(Message)。
Message
Message实际上就是一些指令的集合。它能保持String,int,Runnables等数据类型。
如果我们想要在特定的线程执行Runnables,我们只需将Runnables放到消息中,并将消息放到这个线程的Looper创建
的消息队列中!那么如何放到消息队列中呢?又用到了Handler。