Looper简介:
Looper用于在一个线程中执行一个message loop(消息轮询器)。默认的Thread是没有message loop的,创建一个,通过调用prepare方法来run一个message loop,并且通过执行loop来处理这些消息。
通常Handler和message loop一起活动。
下面这个是官方给出的特殊的例子。
class LooperThread extends Thread {* public Handler mHandler;** public void run() {* Looper.prepare();** mHandler = new Handler() {* public void handleMessage(Message msg) {* // process incoming messages here* }* };** Looper.loop();* }* }
Looper分析:
Looper仅有一个构造方法,还是私有的,我们调用了Looper.prepare()方法。这个时候,会可以创建一个Handler的子类,在looper.loop之前。
public static void prepare() {prepare(true);}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));}
这里,创建一个Looper实例,并放入ThreadLocal中,这里传入的是允许中断的,但是主线程创建的是不允许中断的,主线程不用我们创建。再回到Handler中,在创建Handler的时候,会执行这样的方法。
mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");}mQueue = mLooper.mQueue;
而这个MessageQueue刚好就是在Looper的构造方法中 创建的。这里也说了,只有在调用prepare方法后才能去创建Handler了。Looper.myLooper就是从ThreadLocal中获取Looper了。
最后执行Looper.loop方法。
/*** Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/public static void loop() {final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}final MessageQueue queue = me.mQueue;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerPrinter logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}msg.target.dispatchMessage(msg);if (logging != null) {logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasn't corrupted.final long newIdent = Binder.clearCallingIdentity();if (ident != newIdent) {Log.wtf(TAG, "Thread identity changed from 0x"+ Long.toHexString(ident) + " to 0x"+ Long.toHexString(newIdent) + " while dispatching to "+ msg.target.getClass().getName() + " "+ msg.callback + " what=" + msg.what);}msg.recycle();}}
到这里,for循环,这里会不停的next的从队列中取Message,没取到就继续,取到了,就执行了message.traget.dispatchMeesssage(msg);这target就是Handler,通过handler来分发消息。来执行。
/*** Handle system messages here.*/public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}
好了,如果Message的runnable不为null,就会执行runnable.run。否则,就会判断Handler的callback是不是null,可以在实例化Handler的时候传入,如果返回true,就不会执行HandlerMessage的,两个都会在主线程中来执行。
msg.recycle()会将Message清空,这样,Message会一直这样使用,Message.obtain()会比new Message好的多。
MessageQueue,通过Looper来分发消息列表的消息,,消息不是直接添加到队列中的,而是通过Handler来关联。
ActivityThread,为什么主线程不用执行Looper.prepare以及Looperloop方法。
这样,肯定是主线程中已经调用了这样的方法,查看ActivityThread方法,有一个main方法。
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 libcoreEventLogger.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(newLogPrinter(Log.DEBUG, "ActivityThread"));}Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
Looper.prepareMainLooper(),和Looper.prepare()有什么不同,里面有个boolean值,主线程创建的是不能中止的。
tips
这里可以看到Looper.loop开启后,就会进入一个for(::)的循环了,那么,如果queue.next()取不打消息的时候,就会wait,不会当有消息的时候就会执行,不会死循环的。具体的也是在知乎上看到的一些回答,具体有待研究。
知乎的一些回答:
一:1,epoll模型当没有消息的时候会epoll.wait,等待句柄写的时候再唤醒。2,所有的ui操作都通过handler来发消息操作。比如ui绘制,所以他能被唤醒。二:1.handler机制是使用pipe来实现的2.主线程没有消息处理时阻塞在管道的读端
5548

被折叠的 条评论
为什么被折叠?



