zoukankan      html  css  js  c++  java
  • Android之Handler源码深入分析

    闲着没事,就来看看源码,看看源码的各种原理,会用只是简单的,知道为什么才是最牛逼的。

    Handler源码分析那,从使用的步骤来边用边分析:

    1.创建一个Handler对象:new Handler(getMainLooper(),this);

      这是我常用的一个方式,getMainLooper是获取主线程的Looper,this则是实现CallBack的接口

    看一下Handler的构造函数

     public Handler() {

            this(null, false);

        }

     public Handler(Callback callback) {

            this(callback, false);

        }

    public Handler(Looper looper) {

            this(looper, null, false);

        }

     public Handler(Looper looper, Callback callback) {

            this(looper, callback, false);

     }

     @hide

     public Handler(boolean async) {

           this(null, async);

     }

        @hide

       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());

                }

            }

            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 = callback;

            mAsynchronous = async;

        }

     @hide

     public Handler(Looper looper, Callback callback, boolean async) {

           mLooper = looper;

           mQueue = looper.mQueue;

           mCallback = callback;

           mAsynchronous = async;

     }

    构造函数的最主要代码作用是参数的初始化赋值:

    mLooper = looper;mQueue = looper.mQueue;mCallback = callback;  mAsynchronous = async;

    这四个参数是主要的参数了。

    2.创建一个Message。     Message msg = handler.obtainMessage();

    直接调用Handler的源码:

    public final Message obtainMessage()

        {

            return Message.obtain(this);

        }

    Message中得源码:

    public static Message obtain(Handler h) {

            Message m = obtain();

            m.target = h;

            return m;

        }

    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();

        }

    这里Message是复用的概念,最大能够保持

    private static final int MAX_POOL_SIZE = 50;

    50个Message的对象。

    sPool变量相当于当前的空的没有被使用的Message,通过转换,将当前这个空Message给返回出去。

    Message在使用完之后会被回收的,在下面会有提到。

    3.给Message赋值,并发送Message :    msg.what = 100 ; handler.sendMessage(msg);

    what是Message中得一个储值变量。

    发送Message则在Handler中得最终指向是以下源码:

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

            msg.target = this;

            if (mAsynchronous) {

                msg.setAsynchronous(true);

            }

            return queue.enqueueMessage(msg, uptimeMillis);

        }

     oK,sendMessage给发送给了MessageQueue类,看MessageQueue怎么处理的。

    boolean enqueueMessage(Message msg, long when) {

               

        ...........

                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 {

                    // Inserted within the middle of the queue.  Usually we don't have to wake

                    // up the event queue unless there is a barrier at the head of the queue

                    // and the message is the earliest asynchronous message in the queue.

                    needWake = mBlocked && p.target == null && msg.isAsynchronous();

                    Message prev;

                    for (;;) {

                        prev = p;

                        p = p.next;

                        if (p == null || when < p.when) {

                            break;

                        }

                        if (needWake && p.isAsynchronous()) {

                            needWake = false;

                        }

                    }

                    msg.next = p; // invariant: p == prev.next

                    prev.next = msg;

                }

                if (needWake) {

                    nativeWake(mPtr);

                }

            }

        .......

        }

    截取了中间重要的代码说一下。这个是用来干嘛的??

    其实就是用来排序的,我们知道的是Message有延迟的消息,延迟消息的时间都是不一样的,when是有大小的,将后执行的Message放到后面。

    MessageQueue不是使用一个集合啊或者使用数组去存放的Message,真正排序的是Message的next变量,next变量存放的是当前Message的下一个Message。

    发送之后就执行了一个原生的方法nativeWake,这个在这儿就不去探究了。

    4.handler消息的处理回调Callback.

     public static void loop() {

            

           ........

            for (;;) {

                Message msg = queue.next(); // might block

               

                .....

                msg.target.dispatchMessage(msg);

                           .......

                msg.recycleUnchecked();

            }

        

            ......

        }

    这个那是Looper种的源码,loop就是循环取MessageQueue中得Message的方法。我去掉了代码,我们可以看到调用了Messa得target变量,这个变量存放的就是Handler,dispatchMessage就是用来分发Message的方法了。看DispatchMessage的源码:

     public void dispatchMessage(Message msg) {

            if (msg.callback != null) {

                handleCallback(msg);

            } else {

                if (mCallback != null) {

                    if (mCallback.handleMessage(msg)) {

                        return;

                    }

                }

                handleMessage(msg);

            }

        }

    这个就少了很多了啊!

    看到了把,回调了callback。这样就完成了整个循环流程。

    说一下上面的
    msg.recycleUnchecked()方法。同样,看源码:

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

                }

            }

        }


    从方法名上可以知道这个是用来回收Message的。

    在Message使用完毕之后,不是将MEssage对象销毁,而是存放起来,将其下次重复使用。

    Handler运行大概流程就是这样的了。

    Looper的类的源码分析,回头再解析。

    Android开发交流群:417270671  

    我的github地址: https://github.com/flyme2012 





  • 相关阅读:
    使用 Dockerfile 定制镜像
    UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)
    UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)
    LeetCode Best Time to Buy and Sell Stock 买卖股票的最佳时机 (DP)
    LeetCode Number of Islands 岛的数量(DFS,BFS)
    LeetCode Triangle 三角形(最短路)
    LeetCode Swap Nodes in Pairs 交换结点对(单链表)
    LeetCode Find Minimum in Rotated Sorted Array 旋转序列找最小值(二分查找)
    HDU 5312 Sequence (规律题)
    LeetCode Letter Combinations of a Phone Number 电话号码组合
  • 原文地址:https://www.cnblogs.com/flyme2012/p/4739081.html
Copyright © 2011-2022 走看看