runOnUiThread()的使用以及原理实在是太简单了,简单到笔者开始都懒得单独开一篇文章来写它。当然这里说的简单,是针对对Handler比较熟悉的童鞋而言的。不过麻雀虽小,五脏俱全,runOnUiThread()好歹也算得上是一方诸侯,在子线程切换到主线程的众多方法中,有着自己的一席之地,所以,必须得给它单独列传。
好了,闲话休提,言归正传。runOnUiThread()是Activity类中的方法,它用于从子线程中切换到主线程来执行一些需要再主线程执行的操作。这里先直接看一个例子,看看它是如何使用的:
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.tv_test);
new Thread(new Runnable() {
@Override
public void run() {
//do something takes long time in the work-thread
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText("test");
}
});
}
}).start();
}
}
简单吧,在子线程中直接调用runOnUiThread方法,第15行就切换到主线程了,直接修改UI。如果使用Lambda表达式,看起来就更简单了:
new Thread(() -> {
//do something takes long time in the work-thread
runOnUiThread(() -> {
textView.setText("test");
});
}).start();
相比于通过显示使用Handler,重写AsyncTask方法来说,是不是爽得不要不要的?
不仅仅使用简单,其原理也非常简单,底层实际上也是封装的Handler来实现的,如下是关键代码:
//=========Activity=========
final Handler mHandler = new Handler();
private Thread mUiThread;
final void attach(...){
......
mUiThread = Thread.currentThread();
......
}
/**
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
* not the UI thread, the action is posted to the event queue of the UI thread.
*
* @param action the action to run on the UI thread
*/
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
mHander是Activity的成员变量,在Activity实例化的时候也跟着初始化了,MainActivity继承自Activity,这里mHandler使用的looper自然是main looper了。attach方法也是在主线程中调用的,mUiThread就表示主线程了。第19行的方法就很容易理解了,如果该方法是运行在主线程,Runnable的run方法会马上运行;而如果不是在主线程,就post到主线程的looper的MessageQueue中排队执行。