Android 消息机制 - Message

本文探讨了Android中的消息机制,特别是在项目中使用Handler实现伪递归来判断AsyncTask状态的应用。作者通过研究SDK源码,对Message的生命周期,特别是`recycleUnchecked()`方法进行了分析,该方法用于回收Message并在可能正在使用时执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好久没写博客,实在没得写。。。但是项目中用到了Handler去做伪递归用来判断AsyncTask是否finished 

就对消息机制有了研究的兴趣,看了好久的SDK sources中的源码

现在写一个消息机制的系列,如有错误或不足,请指正,必修改


啥叫伪递归呢  就是在Handler对象的handleMessage方法中,如果AsyncTask的getStatus 方法返回的不是

AsyncTask.Status.FINISHED,就sendEmptyMessage给自己。
因为知道Looper处理消息用的是loop方法  这个方法是在当前线程中执行的,也就是同步执行,所以好奇为什么没有出现
ANR,我当时还用一个while 不断的判断AsyncTask的这个状态,但是直接出现了ANR。
后来才知道发送消息之后只会将这个Message插入到MessageQueue中,即单链表插入。并没有立即执行loop方法
如果是主线程的Looper,会在主线程每次循环最后 执行Looper.loop(); 

虽然这样做并不算是即时的,但是延迟特别小 忽略不计了。。

聊入正题  ----Message  
这是消息的载体,要介绍的内容也比较少(当作很久没写东西的过渡吧)
下面看Message的构造,
Message msg = new Message();
这是调用Message无参数的构造方法:
  /** 
    * Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
    */
    public Message() {
    }
上面写更好的构造一个Message的方法是obtain() ,
   /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
大家有没有注意到了这个sPool, 它就是一个Message,如果它不为null,就返回它作为我们的Message,为null就new 一个返回
那么它在什么时候创建呢,还有为什么有它呢? 
我找到了 recycleUchecked() 方法,这个方法在Looper.loop() 中调用,即处理完这个消息后被调用,看loop() 的实现:
   /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the 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;
        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;
            }

            ........
            msg.target.dispatchMessage(msg);

           .........

            msg.recycleUnchecked();  //  消息通过dispatchMessage处理之后,就去回收它

        }
    }



主要实现在recycleUchecked() 方法:这个方法会回收一个Message 而且这个Message的状态可能是正在使用

而且由于没有权限修饰符,我们直接创建的Message对象调用不了这个方法

   /**
     * Recycles a Message that may be in-use.
     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
     */
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
sPool = this; 这句话表示将调用了recycle方法的Message对象赋值给 sPool,这就解释了为什么用obtain方法更好了
obtain() 会去 使用 被回收了 的Message,这样就避免了创建很多个Message,一种节约资源的做法


说起Message的作用,就是MessageQueue中单链表中的一个消息,它能干嘛呢 ?
Handler的把一条消息发送添加到MessageQueue后,之后当Looper.loop()被调用的时候  就会去处理这个消息 ,
看代码,这是Looper.loop()方法内部


msg.target 是一个Handler 对象,即当初发送它的Handler,现在通过这个target.dispatchMessage()方法将消息又扔回给Handler处理,
看下dispatchMessage(),这个方法在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);
        }
    }
这个callback 是Message的一个Runnable对象,如果没传,就不会执行它,
最后是调用了handleMessage 方法


当然还有很多细节没说,比如MessageQueue的管理,和Looper , Handler 的创建过程等等
这些以后再写。。。。。。。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值