Handler.java
(源码位置: frameworks/base/core/java/android/os/Handler.java)
构造方法:
/**
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
/**
* Constructor associates this handler with the queue for the
* current thread and takes a callback interface in which you can handle
* messages.
*/
public Handler(Callback callback) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
}
/**
* Use the provided queue instead of the default one.
*/
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
/**
* Use the provided queue instead of the default one and take a callback
* interface in which to handle messages.
*/
public Handler(Looper looper, Callback callback) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
}
构造方法可以传一个Looper进来,然后通过looper.mQueue()获取Queue(消息队列)。
如果没有传Looper进来,就通过Looper.myLooper()方法,获取Looper,然后通过looper.mQueue()获取Queue(消息队列)。
根据Looper.myLooper()来判断,这是个单例模式(因为主线程的looper的只有一个,在不同的activity创建handler,都是向主线程的looper发送消息)
接下来追踪Looper.myLooper(),来看looper的源码
Looper.java
(源码位置: frameworks/base/core/java/android/os/Looper.java)
从handler追踪Looper.myLooper()方法
/**
* 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();
}
从本地线程get()出来的,也就是handler所在的线程get()出来的
在activity里面就是主线程,从主线程里获取一个looper
有get()方法,就有对应的set()方法,在Looper里面找:
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
prepare()方法里面new了一个Looper(),set进了当前线程
只要调用这个方法,就会在当前线程放置一个Looper
这是一个静态方法,一个线程里只会调用一次prepare(),也就只有一个Looper
以后再用的话,通过Looper.myLooper()去get()获取就可以了
接下来来看new Looper()的构造方法
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
通过构造方法可以看到,每个looper都会有自己的一个消息队列MessageQueue(),同时还引用了一下当前线程
主线程肯定也会调用prepare()来设置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()}
*/
//准备主线程looper,创建了一个looper就设置进了主线程
public static void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
myLooper().mQueue.mQuitAllowed = false;
}
private synchronized static void setMainLooper(Looper looper) {
mMainLooper = looper;
}
(主线程的looper是需要特殊处理的,因为子线程也可以有looper)
prepareMainLooper()肯定要在主线程被创建的时候调用,主线程一创建就需要把自己的looper建立起来,开启循环,获取消息
接下来看ActivityThread.java
ActivityThread.java
(源码位置: frameworks/base/core/java/android/app/ActivityThread.java)
java里面开启一个程序,要用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);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
在这里看到了Looper.prepareMainLooper()方法
从桌面个上点击启动图标—》开启一个虚拟机—》打开应用(ActivityThread.main())—》Java程序运行起来
开启了一个进程,同步的就有一个线程,Looper.prepareMainLooper()把当前开启的线程就作为了主线程,主线程looper也就建立起来了,主线程就有了一个looper,然后Looper.loop()
接着返回Looper.java类去看loop()方法
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
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();
while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
long wallStart = 0;
long threadStart = 0;
// 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);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
msg.target.dispatchMessage(msg);
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// 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();
}
}
}
looper就是一个死循环,获取消息、分发消息、回收消息。这是一个阻塞的,没有就等待