实验二 现在我们继续在一个没有消息循环的非主线程,进行验证。 复制代码 代码如下: new Thread() { @Override public void run() { Log.i(LOGTAG, "testIn NOT in MainThread isMainThread=" + isInMainThread()); super.run(); } }.start();
正如我们看到的如下日志结果,主线程的Looper(翻译成循环泵,不是很好听)已经被初始化赋值。但是我们新创建的线程的looper还是null。这是因为Android中的线程默认没有一个和它绑定了的消息循环(Threads by default do not have a message loop associated with them. Of course, the method works) 复制代码 代码如下: I/TestInMainThread(32028): isInMainThread myLooper=null;mainLooper=Looper{40d35ef8} I/TestInMainThread(32028): testIn NOT in MainThread isMainThread=false
实验三 继续,我们创建一个绑定了消息循环的线程,根据Android开发者文档说明,以下是一个典型的创建消息循环线程的示例,使用单独prepare()方法和loop()方法来创建一个绑定到Looper的Handler。 复制代码 代码如下: new Thread() { private Handler mHandler; @Override public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Log.i(LOGTAG, "testInNonMainLooperThread isMainThread=" + isInMainThread()); Looper.loop(); }
两个Looper都被初始化赋值了,但是他们是不同的对象。 原理发掘 但是,这是为什么呢,这里面有什么奥秘呢? 好,让我们看以下Looper.class 复制代码 代码如下: // sThreadLocal.get() will return null unless you"ve called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class /** * Initialize the current thread as a looper, marking it as an * application"s main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } /** * Return the Looper object associated with the current thread. * Returns null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); } /** Returns the application"s main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }