..
Android MainLooper的获取原理分析

昨天在使用Handler时,对Handler当中的Looper感兴趣。就研究了一下。网上也有很多Looper的源码分析。这里我也就不说了。

今天我要讲的是Looper当中的两个方法:public static Looper getMainLooper()public static Looper myLooper()。因为好奇为什么在任何地方都能得到MainThread的Looper。

源码分析

源码地址:Looper.java

主要代码摘要:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;  // guarded by Looper.class
public static Looper myLooper() {
	return sThreadLocal.get();
}

public static Looper getMainLooper() {
	synchronized (Looper.class) {
		return sMainLooper;
	}
}

public static void prepareMainLooper() {
	prepare(false);
	synchronized (Looper.class) {
		if (sMainLooper != null) {
			throw new IllegalStateException("The main Looper has already been prepared.");
		}
		sMainLooper = myLooper();
	}
}

这里有三个方法比较奇怪的就是我们会发现sMainLooper = myLooper();获取MainLooper尽然是通过myLooper()获取的。那岂不是获取MainLooper和myLooper一样了吗?

其实这里就是我们的关键。虽然获取MainLooper和获取myLooper都是用的同一个方法,但是只要我们保证prepareMainLooper()只在我们的MainThread中调用唯一的一次,那么我们的sMainLooper将会永远的保存MainThread的Looper。因为在MainThread中的myLooper就是MainLooper。

Android确实也是这样做的,在ActivityThread.java当中就是调用了Looper.prepareMainLooper();.


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());
	
	Security.addProvider(new AndroidKeyStoreProvider());
	
	Process.setArgV0("<pre-initialized>");

	Looper.prepareMainLooper();

	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");
}