概述
我們都知道,更新UI只能在主線程中操作,若是在子線程中訪問(wèn)UI控件,容易引起阻塞。
問(wèn)題來(lái)了,什么是主線程,什么是子線程?
主線程
主線程是指進(jìn)程所擁有的線程。當(dāng)一個(gè)android程序啟動(dòng)時(shí),會(huì)單獨(dú)啟動(dòng)一個(gè)進(jìn)程,默認(rèn)情況下只有一個(gè)。程序啟動(dòng)時(shí),進(jìn)程會(huì)啟動(dòng)一個(gè)主線程,也就是UI線程,主要是負(fù)責(zé)控制UI界面的顯示、更新和控件交互。Android的主線程就是ActivityThread,主線程的入口方法為Main,在main方法中系統(tǒng)會(huì)通過(guò)Looper.prepareMainLooper()來(lái)創(chuàng)建主線程的Looper以及MessageQueue,并通過(guò)Looper.loop()來(lái)開(kāi)啟主線程的消息循環(huán)??匆幌逻^(guò)程。
public static ActivityThread currentActivityThread() {
return sThreadLocal.get();
}
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
// 創(chuàng)建ActivityThread實(shí)例
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
子線程
子線程主要負(fù)責(zé)一些耗時(shí)任務(wù)的執(zhí)行,再配合主線程進(jìn)行UI的更新。
子線程默認(rèn)是沒(méi)有Looper的,若是使用Handler進(jìn)行消息的傳遞,需要手動(dòng)進(jìn)行創(chuàng)建Looper
new Thread(){
@override
public void run(){
Looper.prepare();//創(chuàng)建Looper對(duì)象
Handler handler = new Handler();//這種構(gòu)造方式會(huì)默認(rèn)使用當(dāng)前線程的Looper
Looper.loop();//Looper開(kāi)始工作
}
}.start();
但這種情況下是不能通過(guò)handler更新UI的,因?yàn)閔andler并沒(méi)有實(shí)例化在主線程中。這時(shí)值能處理非更新UI的的操作。如果你想在這個(gè)子線程中更新UI的話,需要這么做
Handler handler = new Handler(Looper.getMainLooper());
這種構(gòu)造方式引用了主線程的Looper,表示放到主UI線程去處理,所以可以更新UI。
判斷當(dāng)前線程是否為主線程。
方法一:使用Looper類判斷
Looper.myLooper() == Looper.getMainLooper();方法二:通過(guò)查看Thread類的當(dāng)前線程
Thread.currentThread() == Looper.getMainLooper().getThread()