Android Looper源码解析
来源:互联网 发布:网络问诊 编辑:程序博客网 时间:2024/05/23 13:45
我们都知道,Android中使用Looper来管理线程的消息队列,我们可以看看Google的介绍
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, call {@link #prepare} in the thread that is to run the loop, and then {@link #loop} to have it process messages until the loop is stopped.
大意是,线程默认是没有消息队列的,此类会在一个线程中运作一个消息循环队列。如果想使用它,先调用Looper.prepare()方法,然后调用Looper.loop()方法。
那它的原理是什么呢?为什么调用Looper的静态prepare()方法就能给当前线程加入Looper呢 ?Looper是如何让一个线程来一直执行其消息队列呢?带着上面的问题,我们今天来解析一下它的源码。
一、prepare()方法:
源码:
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));}
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
可以看出,我们调用prepare()方法,其本质上是调用了私有的prepare(true),并调用了Looper的构造方法创建了一个新的实例,里面初始化了MessageQueue(消息队列,我们以后也会解析其源码)。true表示我们创建的子线程的Looper是一定能被停止的,那么什么线程不能被停止呢?当然是我们的UI线程主线程。我们在来看看 sThreadLocal.set(...); 这行代码:
public void set(T value) { Thread currentThread = Thread.currentThread(); Values values = values(currentThread); if (values == null) { values = initializeValues(currentThread); } values.put(this, value);}
我们可以简单把上面的代码理解为给当前线程加入了指向Looper的变量。我们以后就可以通过当前线程来获取对应的Looper对象。
二、myLooper()方法:
public static @Nullable Looper myLooper() { return sThreadLocal.get();}
其调用的为:
public T get() { // Optimized for the fast path. Thread currentThread = Thread.currentThread(); Values values = values(currentThread); if (values != null) { Object[] table = values.table; int index = hash & values.mask; if (this.reference == table[index]) { return (T) table[index + 1]; } } else { values = initializeValues(currentThread); } return (T) values.getAfterMiss(this); }即本质上是得到当前线程,然后获取其中的Looper对象。所以,调用了prepare()方法之后,当前线程即保留了Looper对象的引用,我们可以通过myLooper()方法获取当前线程的Looper对象。
顺便贴出主线程初始化Looper的代码:
/** * 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(); } }可以看出,其调用了prepare(false)方法来为主线程创建一个不会停止的Looper,并且Looper类中一个静态的Looper对象,指向了主线程的Looper对象。
三、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 block if (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 logger Printer 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.recycleUnchecked(); } }loop()的方法就很简单了,其本质上是先从当前线程中得到Looper对象,然后在得到Looper对象中的MessageQueue对象,从中获取下一个Message对象,然后进行事件的分发。
从上面的解析也可以看出,Looper只是不停的从MessageQueue中不停的取出Message,然后在进行事件处理。而我们的Message的队列管理是由MessageQueue来执行的。
- Android源码解析--Looper
- Android源码解析--Looper
- Android Looper源码解析
- android Looper 源码解析
- Android-源码解析Handler&Looper
- Android Looper、Handler、Message源码解析
- Android中Looper,MessageQueue,ThreadLocal源码解析
- Looper源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android消息机制Handler,MessageQueue,Looper源码解析
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- 深入源码解析Android中的Handler,Message,MessageQueue,Looper
- Android消息队列源码解析(Handler、Looper、Message、MessageQueue)
- Android源码:Handler, Looper和MessageQueue实现解析
- Android Looper 源码笔记
- android Looper源码分析
- Servlet学习笔记(Servlet生命周期&开发Servlet的方法)
- ios常见加密解密方法
- 合并两个排序的链表
- 在java代码中获取JVM参数
- APP开发实战74-广播发送及广播类型
- Android Looper源码解析
- 二维数组根据某个字段排序
- python requests模拟登陆github
- maven入门配置
- C++互斥锁与条件变量的封装使用
- Sql 之 case函数
- 数据字典
- webrtc的编译
- Android样式与主题