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 }

 

 

posted @ 2013-04-20 11:20  g.hui  阅读(210)  评论(0)    收藏  举报