android应用程序消息处理机制之消息发送

来源:互联网 发布:购买ET软件 编辑:程序博客网 时间:2024/06/06 01:09
2、消息的发送
应用程序的主线程准备好消息队列并且进入到消息循环后,其他地方就可以往这个消息队列发送消息了。
查看那ActivityThread。java中的scheduleLaunchActivity() ,这里就先以启动一个activity,
然后发送消息这个例子来入手吧,之后再看看一般我们自己建的handler的处理。
 scheduleLaunchActivity(...){
ActivityClientRecord r = new ActivityClientRecord();

        r.token = token;
        r.ident = ident;
        r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
相关参数封装成一个ActivityClientRecord对象r ,然后使用queueOrSendMessage
往消息队列中加入一个新的消息(标记为:H.LAUNCH_ACTIVITY)
2.1、查看queueOrSendMessage(H.LAUNCH_ACTIVITY, r)
private final void queueOrSendMessage(int what, Object obj) {    
            queueOrSendMessage(what, obj, 0, 0);    
        }    
    
        ......    
        private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {    
            synchronized (this) {    
                ......    
//封装之前传递过来的信息Message对象msg
                Message msg = Message.obtain();    
                msg.what = what;    
                msg.obj = obj;    
                msg.arg1 = arg1;    
                msg.arg2 = arg2;  
//加入到消息队列中,这里的mH为ActivityThread的成员变量,类型是H,继承自Handler。
//这个mH对象,在我们前面第一步骤,实现消息循环时,创建ActivityThread的时候
//就创建了。
                mH.sendMessage(msg);    
            }    
        } 
针对这个mH还是有必要的仔细说清楚
public final class ActivityThread {  
......    
public static final void main(String[] args) {  
......    
ActivityThread thread = new ActivityThread();  
thread.attach(false);    
......  
}  
}  
紧接着看看H这个类
public final class ActivityThread {
......
final H mH = new H();
......
private final class H extends Handler {   
...... 
public void handleMessage(Message msg) {    
......    
switch (msg.what) {      
......    
}    
......    
}      
由于H是继承自Handler的,所以在构造H的时候,也会调用Handler的构造函数
public class Handler{
public Handler(){
......
//获取Looper对象,这里获取到的则是前面在实现消息循环时
//调用Looper.prepareMainLooper()创建的。
mLooper = Looper.myLooper();
......
//使用获取的Looper来访问消息队列
mQueue = mLooper.mQueue;
}
......
final MessageQueue mQueue;  
final Looper mLooper;  
......  
}
回到前面的mH.sendMessage(msg),实际上调用的是mH的父类Handler的sendMessage(msg)
public final boolean sendMessage(Message msg)
{
//接着
return sendMessageDelayed(msg, 0);
}
---->
 public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
//在接着
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
---->
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//设置消息的目标对象,即这个消息由谁来处理。
//这里的this表示这个消息最终由这个Handler来处理
//即由ActivityThread对象的mH成员变量来处理。
msg.target = this;
//这里的uptimeMillis传递进来为当前系统时间+0 ,表示立即处理,不需要延迟
//接下来就是调用这个方法来实现添加消息到消息队列去了
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) {  
......    
final boolean needWake;  
synchronized (this) {  
......    
msg.when = when;  
//Log.d("MessageQueue", "Enqueing: " + msg);  
Message p = mMessages;  
//把消息添加到消息队列,有两种方式:
if (p == null || when == 0 || when < p.when) {  
//消息队列为空,主线程出于空闲等待状态,需要唤醒它。
msg.next = p;  
mMessages = msg;  
//这里的mBlocked 在上面的next()进去空闲等待的时候,mBlocked = true
needWake = mBlocked; // new head, might need to wake up  
} else {  
//消息队列不为空,不需要唤醒主线程,因为它正忙着处理其他消息呢。
//但是新加入的消息,要按照消息执行的时间进行排队。
Message prev = null;  
while (p != null && p.when <= when) {  
prev = p;  
p = p.next;  
}  
msg.next = prev.next;  
prev.next = msg;  
needWake = false; // still waiting on head, no need to wake up  
}  
  
}  
if (needWake) {  
nativeWake(mPtr);   //唤醒主线程的操作,调用JNI操作
}  
return true;  
}  
接着到JNI层
void NativeMessageQueue::wake() {  
mLooper->wake();   //没想到调用的是freameworks层中Looper的wake()
最后到C++层【freameworks】
void Looper::wake() {  
......    
ssize_t nWrite;  
do {  
nWrite = write(mWakeWritePipeFd, "W", 1);  
} while (nWrite == -1 && errno == EINTR);    
.......  
}  
wake()主要是文件描述符mWakeWritePipeFd往管道写入一个"W"字符串。
往管道写入内容的目的是为了唤醒应用程序的主线程。前面我们在分析应用程序的消息循环时说到,
当应用程序的消息队列中没有消息处理时,应用程序的主线程就会进入空闲等待状态,
而这个空闲等待状态就是通过调用这个Looper类的pollInner函数来进入的,
具体就是在pollInner函数中调用epoll_wait函数来等待管道中有内容可读的。
        这时候既然管道中有内容可读了,
应用程序的主线程就会从这里的Looper类的pollInner函数返回到JNI层的nativePollOnce函数,
最后返回到Java层中的MessageQueue.next函数中去,这里它就会发现消息队列中有新的消息需要处理了,
于就会处理这个消息。

原创粉丝点击