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 





  • 相关阅读:
    SpringMVC框架学习笔记(一)
    Spring框架学习笔记(四)
    Spring框架学习笔记(三)
    Spring框架学习笔记(二)
    Spring框架学习笔记(一)
    单点登录与权限管理本质:cookie安全问题
    单点登录与权限管理本质:单点登录介绍
    单点登录与权限管理本质:HTTP重定向
    单点登录与权限管理本质:session和cookie介绍
    「单点登录与权限管理」系列概述
  • 原文地址:https://www.cnblogs.com/flyme2012/p/4739081.html
Copyright © 2011-2022 走看看