Android Handler Essentials

Essentials系列主要是讲原理和实现,应用可以参考API说明和APIDemo
一直觉得搞Android的开发,还是看原生的SDK说明 + source code比较好。关键是要思考。

搞Handler也一样,先上原版的说明。
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

[size=large]There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own. [/size]

Scheduling messages is accomplished with the [i]post, postAtTime(Runnable, long), postDelayed, sendEmptyMessage, sendMessage, sendMessageAtTime, and sendMessageDelayed[/i] methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message object containing a bundle of data that will be processed by the Handler's handleMessage method (requiring that you implement a subclass of Handler).

When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.

When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will than be scheduled in the Handler's message queue and processed when appropriate.


Thread ---- Looper
Looper ---- MessageQueue
一个Thead里面有一个looper [thread 跟looper的关系 注1]
一个Looper里面有一个MessageQueue

[注1 可以看Looper的api介绍,有讲怎么在自定义的thread里面建立Looper]


[size=medium][b]1. Insert message to MessageQueue(入[color=red]链表[/color])[/b][/size]
看一句常用的code
mHandler.sendEmptyMessage(1);

这个send的动作是阻塞式(synchronized)的,如果有其它thread也在向同一个handler send message,那当前thread就会被block

Message msg = Message.obtain();
sendMessageAtTime
sent = queue.enqueueMessage(msg, uptimeMillis);

MesaageQueue
Message mMessages;
这里是一个[color=red]链表[/color],按when排序,从小到大的链表。
enqueueMessage就是按when插入链表的动作

[size=medium][b]2. 出[color=red]链表[/color][/b][/size]
先查出链表的method,
猜测
next, poke, pullNextLocked

final Message next() {
// 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();
}
}
}

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;
}

好,就是这个了next(), pullNextLocked()

再找invoke这个method的地方
先猜,一定是个一直在跑的死循环
结果找到
Looper.java
public static final void loop() {

while (true) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);
}
}

那谁又在invoke这个呢?
请教Changer大神
找到了调用Looper.loop()的地方
在ActivityManagerService
static class AThread extends Thread {
public void run() {
Looper.prepare();

android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);

ActivityManagerService m = new ActivityManagerService();

synchronized (this) {
mService = m;
notifyAll();
}

synchronized (this) {
while (!mReady) {
try {
wait();
} catch (InterruptedException e) {
}
}
}

Looper.loop();
}
}


[color=gray][i]原来touchEvent也是由这个Looper来存储的。[/i] //Point 1 这句是错的。Touch等事件传递不走这边。!!![/color]

这个Looper.loop() might block
UI的display和消息的队列是一起建立起来的。
并且是跑在一个Thread的里面的,是序列化的动作。

问题1:在loop()取不到消息就会阻塞,那我写的onCreate(), onStart()函数怎么跑?!!!他们都在一个thread里面哎。

刚刚想了一下,是不是跑到Looper.loop()的时候,onCreate(), onStart(), onResume()都已经跑完了。

又请教了下Changer大神。真的已经跑完了。大神作用就是大啊。

[color=gray]Looper.loop()在所有的东西都显示出来以后,就调用起来了。然后等待消息驱动,这就是所谓的事件驱动啊。

问题2: 可是,这个时候我touch一下,又是谁往MessageQueue里面插入touch消息的呢?
我想消息肯定是从其它Thread里面插入的。// Point 2 ,error !!![/color]
这个再议。关于事件传递,关于view的显示我们先搁着。

[color=red]这次强调一下,TouchEvent的传递跟Looper的MessageQueue是两码事。灰化的文字是错的。[/color]

[size=medium][b]3. 整个Flow[/b][/size]
现在回过头来看下整个Flow

当Looper.loop调起的时候,
如果消息,它就会分发出去(这里面还包括消息时间未到的情况)。
如果没有,它就会等待。
看code, MessageQueue.java next()
            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) {
}
}

直到其它的Thread,通过Handler发了一条消息,插入MessageQueue,然后会Notify出来。
这样,整个Flow就跑通了。
看code, MessageQueue.java
            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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值