ActivityThread.java 的 main主函数启动入口
public static final void main(String[] args) {
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name;
if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName();
else name = "<unknown>";
Log.i(TAG, "Main thread of " + name + " is now exiting");
}
Looper.java
从prepareMainLooper方法的注释可以理解,初始化当期线程,而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.
* {@link #prepare()}
*/
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
private synchronized static void setMainLooper(Looper looper) {
mMainLooper = looper;
}
/** Returns the application's main looper, which lives in the main thread of the application.
*/
public synchronized static final Looper getMainLooper() {
return mMainLooper;
}
初始化当前线程,之后把一个初始化的Looper关联线程,在Looper初始化的时候做了一些操作就是初始化了一个消息队列MessageQueue即通过Looper来管理MessageQueue,通过调用Looper.myLooper()可以获得当前线程的Looper对象,但是Looper的构造函数是私有的,外界无法直接实例化之;要实例化,只有通过Looper::prepare()
// sThreadLocal.get() will return null unless you've called prepare().
private static final ThreadLocal sThreadLocal = new ThreadLocal();
/** 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 final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
looper里面的消息队列进行循环机制,执行消息队列里面的一个个消息,注意 msg.target是个Handler对象
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
轮循中开始处理系统的一个个消息,两种情况一种正常消息处理,一种回掉处理;其中
handleMessage(msg)为需要用户自己继承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);
}
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
理解下HandlerThread,你会发现HandlerThread继承Thread,HandlerThread::run()里面调用了Looper的初始化prepare();和looper()。
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
Process.setThreadPriority(mPriority);
notifyAll();
}
onLooperPrepared();
Looper.loop();
mTid = -1;
}
理解Handler,从下面的Handler构造函数可以了解Handler的构造是需要Looper对象的,没有参数Looper的构造函数是用当前线程的looper对象;而当然你也可以通过HandlerThread施行run后就有了looper对象,通过对外的接口getLooper()可以获取此Looper对象,MessageQueue在looper中是一个属性,所以你需要记忆这个。
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;
}
/**
* Use the provided queue instead of the default one.
*/
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
说明:对于以上的理解我在最后会有实例来验证说明,到这里我们的疑问是现在我们想知道 消息是怎么封装的,消息是怎么放入消息队列的?
消息的入消息队列
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
* /
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
* /
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
通过上面的理解,用实例来验证上面的理解,下面是我以前项目中写的代码。
实例一:在一个activity耗时的操作方法中自己起了一个线程
Thread th = new Thread() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
Toast.makeText(MailView.this, "�ʼ����ͳɹ�",
Toast.LENGTH_LONG).show();
}
}
)
}
}
th.start();
实例二:Service中,这里注意下,Message的对象创建Message::obtain(),这个对象也可以是Handler的obtainMessage()来创建。
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_TIMER:
mWorker = new HandlerThread("MyWorker");
mWorker.start();
mWorkerHandler = new Handler(mWorker.getLooper());
mWorkerHandler.postDelayed(new MessageReceiveTask(),
SECONDRESOLVERMESSAGE);
break;
}
}
};
public void onCreate() {
super.onCreate();
Log.i(Constant.TAG_INFO,
"StartService*****************************************");
Message msgget = Message.obtain();
msgget.what = MSG_TIMER;
handler.sendMessageDelayed(msgget, SECONDRESOLVERMESSAGELONG);
}
class MessageReceiveTask implements Runnable {
public void run() {
try {
loadInitInboxData();
} catch (Exception e) {
Log.i(Constant.TAG_EXCEPTION, "MessageReceiveTask : " + e);
}
mWorkerHandler.postDelayed(this, SECONDRESOLVERMESSAGE);
}
}
从上面我写的代码可以看到发送有两种方式,sendMessage(m)和postDelayed(r)两种,我列出源码
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
/**
* Causes the Runnable r to be added to the message queue, to be run
* after the specified amount of time elapses.
* The runnable will be run on the thread to which this handler
* is attached.
*
*/
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
/**
* Causes the Runnable r to be added to the message queue, to be run
* at a specific time given by <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* The runnable will be run on the thread to which this handler is attached.
* @see android.os.SystemClock#uptimeMillis
*/
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
下班了,。。。。。。上面是一个流程的了解,下面我们需要对细节的了解,这个有待继续。
下面是message的创建,请注意这里,先从池中取出,需要明白下面是个单向链表的形式,从注释中可以了解到:// sometimes we store linked lists of these things
Message next;如果在池中没有就从新new一个对象。
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (mPoolSync) {
if (mPool != null) {
Message m = mPool;
mPool = m.next;
m.next = null;
return m;
}
}
return new Message();
}
注意message要是用完后,需要回收放入池中
/**
* Return a Message instance to the global pool. You MUST NOT touch
* the Message after calling this function -- it has effectively been
* freed.
*/
public void recycle() {
synchronized (mPoolSync) {
if (mPoolSize < MAX_POOL_SIZE) {
clearForRecycle();
next = mPool;
mPool = this;
}
}
}
从// might block这个注释说开来,
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block 取消息队列中的消息,如果没有就有可能堵塞
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}
继续说明消息是怎么取的
final Message next() {
boolean tryIdle = true;
while (true) {
long now;
Object[] idlers = null;
// Try to retrieve the next message, returning if found.
synchronized (this) {
now = SystemClock.uptimeMillis();
Message msg = pullNextLocked(now); 具体的通过单向链表方式来操作的,看这个方法的具体内容就明白了。
if (msg != null) return msg;
if (tryIdle && mIdleHandlers.size() > 0) {
idlers = mIdleHandlers.toArray();
}
}
// There was no message so we are going to wait... but first,
// if there are any idle handlers let them know.
boolean didIdle = false;//no idle
if (idlers != null) {
for (Object idler : idlers) {
boolean keep = false;
try {
didIdle = true;
keep = ((IdleHandler)idler).queueIdle();
} catch (Throwable t) {
Log.e("MessageQueue",
"IdleHandler threw exception", t);
RuntimeInit.crash("MessageQueue", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
}
// While calling an idle handler, a new message could have been
// delivered... so go back and look again for a pending message.
if (didIdle) {
tryIdle = false;
continue;
}
synchronized (this) {
// No messages, nobody to tell about it... time to wait!
try {
if (mMessages != null) {
if (mMessages.when-now > 0) {
Binder.flushPendingCommands();
this.wait(mMessages.when-now); 这里需要说明的是堵塞等待一个特定的时间
}
} else {
Binder.flushPendingCommands();
this.wait(); 堵塞 ,期待唤醒
}
}
catch (InterruptedException e) {
}
}
}
}
下面是通过比较当前系统的真实时间long来和消息的message的when时间值来比较,如果当前时间大于或等于消息时间,就把当前节点取出来,把下一个赋值给当前节点。
final Message pullNextLocked(long now) {
Message msg = mMessages;
if (msg != null) {
if (now >= msg.when) {
mMessages = msg.next;
if (Config.LOGV) Log.v(
"MessageQueue", "Returning message: " + msg);
return msg;
}
}
return null;
}
消息的入对列也是单向列表式的操作
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
上面的msg.when!=0是因为之前这个方法被调用前没有被赋值过,如果被赋值过,则说明已经被使用中了。
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p; 把当前的节点赋值给传进来的message的下一个,而下面一句则是把传进来的message作为最新的当前节点。
mMessages = msg;
下面一句是唤醒,通过上面的判断有消息入队,则进行唤醒来进行处理。
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}