Android应用程序Handler机制详解

来源:互联网 发布:人工智能原理 编辑:程序博客网 时间:2024/05/18 15:23

之前听朋友讲过handler,之后自己看了下handler的源码(Read The Fucking Source Code。)决定写下关于handler的博客。

1、handler 消息处理器,负责处理消息。

2、Message 消息,包含消息id,被处理的对象。

3、MessageQueue 消息队列,存放Handler发送过来的Message

4、looper 消息泵,不间断的从MessageQueue消息队列中抽取消息。

简单的比喻looper就是水泵,MessageQueue储水的池塘,Message就是水,Handler就是操作的人。

Android应用程序是消息驱动的,并且是全局的消息驱动循环系统,Android通过Looper,handler来实现消息循环机制。


Message:消息对象,MessageQueue中存放的对象,一个MessageQueue中包含多个Message;

MessageQueue:存放Message的数据结构;

Looper:可以看成一个死循环,一直循环去MessageQueue中取Message,每个Looper创建的同时都会创建一个MessageQueue

Handler:消息的处理者;Handler可以通过sendMessage来发送一个消息到MessageQueue中,也可以通过handlerMessage来处理掉一个Message

起初接触这个是子线程更新主线程界面的时候用的,只知道Handler与Message,那我们就从Message与Handler的源码开始看起:

这是我第一次接触到Handler

 Handler handler = new Handler(){            @Override            public void handleMessage(Message msg) {                super.handleMessage(msg);                //这里处理更新界面的操作            }        };        new Thread(){            @Override            public void run() {                super.run();                Message msg = new Message();                msg.obj = 1;                handler.sendMessage(msg);            }        }.start();

先来看Message

Message源码:http://androidxref.com/2.3.7/xref/frameworks/base/core/java/android/os/Message.java
这里说下看源码可以到:http://androidxref.com/看源码
Message源码位置:/frameworks/base/core/java/android/os/Message.java

public final class Message implements Parcelable {    public int what;    public int arg1;     /*package*/ Handler target;    /*package*/ Runnable callback;    // sometimes we store linked lists of these things    /*package*/ Message next;......    private static final Object sPoolSync = new Object();    private static Message sPool;    private static int sPoolSize = 0;    private static final int MAX_POOL_SIZE = 50;    private static boolean gCheckRecycle = true;    /**     * 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();    }......    /**     * Return a Message instance to the global pool.     * <p>     * You MUST NOT touch the Message after calling this function because it has     * effectively been freed.  It is an error to recycle a message that is currently     * enqueued or that is in the process of being delivered to a Handler.     * </p>     */    public void recycle() {        if (isInUse()) {            if (gCheckRecycle) {                throw new IllegalStateException("This message cannot be recycled because it "                        + "is still in use.");            }            return;        }        recycleUnchecked();    }......    /**     * 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++;            }        }    }......}
当看到12行Message next;的注释:有时我们将把这东西存储链表,并看到代码16行private static Message sPool;就会想打Message本身就是链表数据结构;看到19行private static final int MAX_POOL_SIZE = 50;这个链表最大长度是50.接下来我们看27行的obtain()方法,if(sPool != null){//如果sPool中有Message    Message m = sPool;//去sPool中获取第一个Message    sPool = m.next; //sPool去掉第一Message    m.next = null;//把去除的Message的next置空    sPoolSize--;sPool 的长度减去1;    return m;获得这个Message}

return new Message();//如果sPool 没有Message就新建一个

看到这里我之前都是直接new Message();这样的话消耗资源比较多。
最好的方法就是 Message msg = Message.obtain();

再看void 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再把他放回sPool中,并且把所有属性置空。当sPoolSize

好了大致了解了Message,再看看handler.sendMessage(msg);把Message放到了那里

Handler源码位置:/frameworks/base/core/java/android/os/Handler.java

 public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }

sendMessage最后调用的是

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

那么MessageQueue 有是从哪里来的?

public Handler(Callback callback, boolean async) {        .....        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;    }

看Handler的构造函数mQueue = mLooper.mQueue;是从Looper中得来的,那么Looper是从哪里初始化的呢?
Looper 和MessageQueue其实是在ActivityThread里就初始化了
ActivityThread的源码位置:frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {                public static final void main(String[] args) {                    ......                    Looper.prepareMainLooper();                    ......                    Looper.loop();                }            }

我们再来看看Looper.prepareMainLooper();都干了什么,
Looper源码位置:/frameworks/base/core/java/android/os/Looper.java

public final class Looper {        ....        private Looper(boolean quitAllowed) {            mQueue = new MessageQueue(quitAllowed);            mThread = Thread.currentThread();        }        ....        private static void prepare(boolean quitAllowed) {            if (sThreadLocal.get() != null) {                throw new RuntimeException("Only one Looper may be created per thread");            }            sThreadLocal.set(new Looper(quitAllowed));        }        ....        /**         * Initialize the current thread as a looper, marking it as an         * application's main looper. The main looper for your application         * is created by the Android environment, so you should never need         * to call this function yourself.  See also: {@link #prepare()}         */        public static void prepareMainLooper() {            prepare(false);            synchronized (Looper.class) {                if (sMainLooper != null) {                    throw new IllegalStateException("The main Looper has already been prepared.");                }                sMainLooper = myLooper();            }        }        ....     public static void loop() {       ......        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            .....            msg.recycleUnchecked();        }    }    }

看looper源码知道初始化looper的时候同时mQueue = new MessageQueue(quitAllowed);新建了一MessageQueue

在ActivityThread中调用loop();这个方法就是一个死循环一直循环去MessageQueue中拿Message并msg.target.dispatchMessage(msg);,其中msg.target 是handler,这里就是通过handler去处理Message,处理完了 然后通过msg.recycleUnchecked();回收。这个基本上走了一遍,其中有细节东西很多。大家可以去看看源码!

未完待续。。。

0 0
原创粉丝点击