概述
我们都知道,更新UI只能在主线程中操作,若是在子线程中访问UI控件,容易引起阻塞。
问题来了,什么是主线程,什么是子线程?
主线程
主线程是指进程所拥有的线程。当一个android程序启动时,会单独启动一个进程,默认情况下只有一个。程序启动时,进程会启动一个主线程,也就是UI线程,主要是负责控制UI界面的显示、更新和控件交互。Android的主线程就是ActivityThread,主线程的入口方法为Main,在main方法中系统会通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue,并通过Looper.loop()来开启主线程的消息循环。看一下过程。
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();
// 创建ActivityThread实例
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");
}
}
子线程
子线程主要负责一些耗时任务的执行,再配合主线程进行UI的更新。
子线程默认是没有Looper的,若是使用Handler进行消息的传递,需要手动进行创建Looper
new Thread(){
@override
public void run(){
Looper.prepare();//创建Looper对象
Handler handler = new Handler();//这种构造方式会默认使用当前线程的Looper
Looper.loop();//Looper开始工作
}
}.start();
但这种情况下是不能通过handler更新UI的,因为handler并没有实例化在主线程中。这时值能处理非更新UI的的操作。如果你想在这个子线程中更新UI的话,需要这么做
Handler handler = new Handler(Looper.getMainLooper());
这种构造方式引用了主线程的Looper,表示放到主UI线程去处理,所以可以更新UI。
判断当前线程是否为主线程。
-
方法一:使用Looper类判断
Looper.myLooper() == Looper.getMainLooper();
-
方法二:通过查看Thread类的当前线程
Thread.currentThread() == Looper.getMainLooper().getThread()
网友评论