Hander 机制(驱动模型理解)

一,概要

 Android 应用是基于事件驱动的,每个事件(UI绘制、滑动等)都会转化为一个系统消息,即 Message。然后,系统  looper 通过维护一个消息队列 messageQueue 来完成消息的分发处理.  

二,介绍

1.Message( 快递)

public final class Message implements Parcelable {

        /*package*/ static final int FLAG_IN_USE = 1 << 0;

        /** If set message is asynchronous */
        /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;

        /** Flags to clear in the copyFrom method */
        /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;

        /*package*/ int flags;
        
        /*package*/ Handler target;

        /*package*/ Runnable callback;

        // sometimes we store linked lists of these things
        /*package*/ Message next;
}

 

message 是handler机制中的最小单位。(我们看下,我们比较陌生的成员变量 和方法)

  1.target:是发送和处理该 message 的handler

  2. callback:即是我们post的 Runnable。可以理解,我们的message 有两种:1.传递数据 ,2.一种是传递Runnable 接口

  3.flags: 是message 的一种标识:

FLAG_ASYNCHRONOUS(同步) FLAG_IN_USE(使用中) FLAGS_TO_CLEAR_ON_COPY_FROM(清除标记)

 4. next : 指向下一个message  (message 是 基于链表结构 )

 5 .static Message obtain():获取message方法:

public static Message obtain() {
//sPoolSync 线程同步对象锁
        synchronized (sPoolSync) {
//sPool (message 静态变量,message消息列表的根节点)
            if (sPool != null) {
                //将根节点,赋给变量m
                Message m = sPool;
                //根节点指向下一个message
                sPool = m.next;
                //变量m 的下一个message指向null,把m 从链表完全割离
                m.next = null;
                m.flags = 0; // clear in-use flag
                //链表长度减一
                sPoolSize--;
                return m;
            }
        }
        //如果初始时候,链表为空,则新建一个message
        return new Message();
    }

 6. public void  recycleUnchecked() :释放回收message方法

public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it"is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }

 //message 成员变量置为空
 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) {
            //MAX_POOL_SIZE message 默认的最大容量
            if (sPoolSize < MAX_POOL_SIZE) {
                //当前message 的 next 指向了 message列表头部
                next = sPool;
                //成功将回收释放的message 插到列表头部
                sPool = this;
                //数量++
                sPoolSize++;
            }
        }
    }

 因此,我们在使用message 的时候,尽量要用obtain()  而不是 new Message(),  这样可以 复用对象,避免多次创建对象,导致内存的增长

2.MessageQueue(传送带)

   1.boolean enqueueMessage(Message msg, long when) :向 message 链表 中加入新的message 

boolean enqueueMessage(Message msg, long when) {
        //如果message  没有 持有handler
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in
use.");
        }

        synchronized (this) {
//如果messagequeue 所在 线程死亡,queue 中的message 回收
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
//mMessages 标记最近的一个 message    
            Message p = mMessages;
            boolean needWake;
//如果 mMessages 为null, 直接将添加的新消息插入链表头部
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
      
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                //轮询message列表,插入链表中
                for (;;) {
                    prev = p;
                    p = p.next;
                    //如果加入的message 时间小于 p 的时间  
                    if (p == null || when < p.when) {
                        break;
                    }
                    //需要唤醒,且p 是异步 message
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                //插入p(message) 的前面 
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
             
            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                //native 层 唤醒方法
                nativeWake(mPtr);
            }
        }
        return true;

2.Message next() : 获取下一个 message

 Message next() {
       
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
               //如果设置了屏障,直到找到下一个同步消息之前的异步消息(后面我会提到)
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
               //普通我们发的消息为异步消息,只会走到这个方法(target 不会为null,Asynchronous且为 false)
               // mMessage  赋给 msg 返回, mMessage 并指向 mMessage 的下一个message ,    
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
        }

从源码可知,messageQueue 负责 将新的 message 加入链表,和取出链表

3.Looper(快递公司)

                 1.一个线程中有几个looper?

                 2.主线程 和 子线程 中使用的注意事项

public final class Looper {
 
    private static final String TAG = "Looper";
    //thread 所持有 副本对象 ThreadLocal(涉及到Java 并发,后期会说下)
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    //主线程的looper   
    private static Looper sMainLooper;  
    //looper 所持有的 MessageQueue 
    final MessageQueue mQueue;
    //looper 所在的线程
    final Thread mThread;

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
}

1.从 中构造函数中,可以看到,looper 维持着一个线程 和 一个 MessageQueue()

2.私有的构造函数,如果使用的时候,怎么获取的,所以我们找一找它的其它的 替代方法。

   private static void prepare(boolean quitAllowed)

   public static void prepareMainLooper()

 1.private static void prepare(boolean quitAllowed) 创建主线程 looper

public final class Looper {

 private static void prepare(boolean quitAllowed) {
      //如果该线程存在looper 直接抛异常
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
     //将looper 通过 threadLocal 赋给 当前线程
        sThreadLocal.set(new Looper(quitAllowed));
    }

}


public class ThreadLocal<T> {

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
}
public class ThreadLocal<T> {

// 此时的 T->Looper
 public T get() {
 //获取当前线程的 threadLocal
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
//线程中维持着一个 ThreadLocal.ThreadLocalMap  类型的 threadLocals 变量
//该map 是一个  Entry(ThreadLocal<?> k, Object v)  类型对象
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

//获取 该线程 looper
 private Entry getEntry(ThreadLocal<?> key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }

}

 1.线程中只能持有一个looper       

2.public static void loop()  无限循环 获取 message

 

 public static void loop() {
      // 获取当前线程looper 对象
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
       //获取looper中持有的  MessageQueue 
        final MessageQueue queue = me.mQueue;

        //开启无限循环     
        for (;;) {
            // messageQueue 获取 msg
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
         
            try {
             //msg.target=>handler
             //handler.dispatchMessage() =>方式msg的 handler  处理message 
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
          
            //msg 消耗完直接回收,加到闲置message链表表头,前面已讲
            msg.recycleUnchecked();
        }
    }

3.public static void prepareMainLooper() 

    主线程中创建 的looper

public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

 4.Handler (快递员)

Handler 使我们平常使用最多的,常用使用方法

1.Handler handler =new Handler()

2.handler.sendMessenge()....

3..handler.post(Runnable b)...

4.dispatchMessage /handleMessage

 

public Handler(Callback callback, boolean async) {
        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());
            }
        }
        //获取 looper
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //消息 messagequeue
        mQueue = mLooper.mQueue;
        //handler callback
        mCallback = callback;
       //是否为异步handler 
        mAsynchronous = async;
    }

 new Handler()

1.将handler 和 looper 关联起来,所以,在使用handler的前,必须要新建 looper

 public final boolean post(Runnable r) {
       return  sendMessageDelayed(getPostMessage(r), 0);
 }

 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

handler .post() ---->handler.sendMessage()-------->sendMessageAtTime-->MessageQueue.enqueueMessage(queue, msg, uptimeMillis)  :是不是似曾相识,哈哈,没错,回到了我们前面讲的,MessageQueue 中(忘记了,可以看下前面)。


//looper.looper() 方法中,获取了message中的handler ,并调用dispatchMessage() 方法
public class Handler {

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
           // handler.post(callback)
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                // new Handler(mCallback)
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //最后调用handler中的  handleMessage 方法
            handleMessage(msg);
        }
    }
}


public final class Looper {

 public static void loop() {
   for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
 
        msg.target.dispatchMessage(msg);
  }
}

 

handler 发送message 后, 必须通过looper.loop() 才能让发动机动起来,传送带开始传送事件  !

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值