android之Looper
Looper是什么?
刚开始对Looper很迷惑,一直想不明白到底有啥作用,经过这几天的研究终于算是有点明白了。先看官方文档中的解释:Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, callprepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
大致是说:1)Looper是为Thread工作的2)为Thread工作提供一个消息循环3)线程默认情况下没有Looper,想要创建Looper需要我们在此线程中先调用prepare()然后再调用loop()开始循环直到loop停止。
深入Looper
如上所说,Looper为Thread提供了一个消息循环,通过此循环Thread可以不断的取出消息并处理。线程默认情况下没有Looper,但android的主线程却不一样了,系统默认为主线程设置了一个looper,所以如果我们在主线程中创建Handler时不需要创建looper.说到这不妨先说一下handler与looper的关系。handler是为了发送和处理消息的。发送到looper所管理的消息队列中。一般情况下,我们是不需要自己创建looper的,我们只有在需要实现子线程与子线程之间的通信时才需要自己创建looper,因为这样的话我们就需要在其中一个子线程中new 一个handler对象,而这样就需要我们为此子线程先创建一个looper,看官方文档中的例子:
1 class LooperThread extends Thread { 2 public Handler mHandler; 3 4 public void run() { 5 Looper.prepare(); 6 7 mHandler = new Handler() { 8 public void handleMessage(Message msg) { 9 // process incoming messages here 10 } 11 }; 12 13 Looper.loop(); 14 } 15 }
如果我们没有创建looper就直接new handler会得到这样的错误:"Can't create handler inside thread that has not called Looper.prepare()"
源码分析
Looper部分源码
1 2 public class Looper { 3 //用来保存looper 4 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 5 //主线程looper对象 6 private static Looper sMainLooper; // guarded by Looper.class 7 //looper操作的消息队列 8 final MessageQueue mQueue; 9 //looper依附的线程 10 final Thread mThread; 11 12 //实例化一个允许quit的looper 13 public static void prepare() { 14 prepare(true); 15 } 16 17 //实例化looper可以指定是否允许退出 18 private static void prepare(boolean quitAllowed) { 19 if (sThreadLocal.get() != null) { 20 throw new RuntimeException("Only one Looper may be created per thread"); 21 } 22 sThreadLocal.set(new Looper(quitAllowed)); 23 } 24 25 //为主线程实例化一个looper,不允许quit 26 public static void prepareMainLooper() { 27 prepare(false); 28 synchronized (Looper.class) { 29 if (sMainLooper != null) { 30 throw new IllegalStateException("The main Looper has already been prepared."); 31 } 32 sMainLooper = myLooper(); 33 } 34 } 35 36 public static Looper getMainLooper() { 37 synchronized (Looper.class) { 38 return sMainLooper; 39 } 40 } 41 42 //循环体,在此循环体中进行消息的循环,并调用handler的dispatchMessage方法进行消息的处理 43 public static void loop() { 44 final Looper me = myLooper(); 45 if (me == null) { 46 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); 47 } 48 final MessageQueue queue = me.mQueue; 49 50 // Make sure the identity of this thread is that of the local process, 51 // and keep track of what that identity token actually is. 52 Binder.clearCallingIdentity(); 53 final long ident = Binder.clearCallingIdentity(); 54 55 for (;;) { 56 Message msg = queue.next(); // might block 57 if (msg == null) { 58 // No message indicates that the message queue is quitting. 59 return; 60 } 61 62 // This must be in a local variable, in case a UI event sets the logger 63 Printer logging = me.mLogging; 64 if (logging != null) { 65 logging.println(">>>>> Dispatching to " + msg.target + " " + 66 msg.callback + ": " + msg.what); 67 } 68 69 msg.target.dispatchMessage(msg); 70 71 if (logging != null) { 72 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); 73 } 74 75 // Make sure that during the course of dispatching the 76 // identity of the thread wasn't corrupted. 77 final long newIdent = Binder.clearCallingIdentity(); 78 if (ident != newIdent) { 79 Log.wtf(TAG, "Thread identity changed from 0x" 80 + Long.toHexString(ident) + " to 0x" 81 + Long.toHexString(newIdent) + " while dispatching to " 82 + msg.target.getClass().getName() + " " 83 + msg.callback + " what=" + msg.what); 84 } 85 86 msg.recycle(); 87 } 88 } 89 90 //得到当前线程的looper 91 public static Looper myLooper() { 92 return sThreadLocal.get(); 93 } 94 95 public static MessageQueue myQueue() { 96 return myLooper().mQueue; 97 } 98 99 private Looper(boolean quitAllowed) { 100 mQueue = new MessageQueue(quitAllowed); 101 mRun = true; 102 mThread = Thread.currentThread(); 103 } 104 105 public void quit() { 106 mQueue.quit(); 107 } 108 109 /** 110 * Return the Thread associated with this Looper. 111 */ 112 public Thread getThread() { 113 return mThread; 114 } 115 116 /** @hide */ 117 public MessageQueue getQueue() { 118 return mQueue; 119 } 120 }


浙公网安备 33010602011771号