Android 消息处理机制2(从源码分析)

来源:互联网 发布:犀牛软件模型立面 编辑:程序博客网 时间:2024/05/17 22:30

跟随着上篇 Android 消息处理机制1(从源码分析),下面介绍 “猪脚光环的” : Handler 、Message 、MessageQueue Looper。并以Java 程序模拟安卓的消息处理机制

Handler 在前面已经介绍过了,从创建Handler 实例顺藤摸瓜…

Handler 原理

  1. Handler 封装了消息的发送 (— > 发给谁) 【默认指向自己】
  2. Handler 的依赖对象 Looper 意为:轮询 . 其内部包含了一个消息队列也就是 MessageQueue ,MessageQueue 封装了消息( Message)的载体 所有Handler 发送的信息都走向这个消息队列

两大用途

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

Handler 的源码分析

...public Handler() {        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 = null;    }    ...

由源码得出:

Post:Post允许把一个Runnable对象入队到消息队列中。它的方法有:post(Runnable),postAtTime(Runnable,long),postDelayed(Runnable,long).
sendMessage:sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:sendEmptyMessage(int), sendMessage(Message).sendMessageAtTime(Message,long).sendMessageDelayed(Message,long)。
  从上面的各种方法可以看出,不管是post还是sendMessage都具有多种方法,它们可以设定Runnable对象和Message对象被入队到消息队列中,是立即执行还是延迟执行。

Looper 原理

本质是一个死循环 不断地从 MessageQueue 中取出数据,有消息就取出,没消息就阻塞。

Looper中重要的方法:

static void loop()Run the message queue in this thread.

为什么Handler 内部要与 Looper 进行关联?

不关联Handler 如何向MessageQueue 发送Message呢

总的来说: Handler 负责发送消息,Looper 负责接收消息并把消息回传给 Handler , 而 MessageQueue 是就是存储 Message 的容器

Framework 源码简析

UI 线程 ActivityThread 创建 Looper Message

这里写图片描述


这里写图片描述


这里写图片描述


new Looper(); 后做了那些操作呢?

这里写图片描述

如何取出 当前线程关联的 Looper 对象?

public static Looper myLooper() {        return sThreadLocal.get();}

Handler 发送消息到 MessageQueue (消息入列)

这里写图片描述

Handler取出 当前线程关联的 Looper 对象 是为了Looper 中MessageQueue 对象进行发送消息Message

Tips:对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者Handler.obtainMessage()获取。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的,才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是调用的Message.obtain()。  

Java 程序实现

下面代码由 Framework 源码拷贝出来进行分析,每一位安卓工程师都应该拥有一份 Framework 源码,以便了解android.

ActivityThread (程序入口)

public class ActivityThread {    public static void main(String[] args) {        //初始化主线程的 Looper 对象        Looper.prepareMainLooper();        final Handler handler = new Handler() {            @Override            public void handleMessage(Message msg) {                super.handleMessage(msg);                System.out.println("接收到 what = " + msg.what);                System.out.println("Thread " + Thread.currentThread().getName());            }        };        handler.sendEmptyMessage(1);        handler.sendEmptyMessage(2);        new Thread(new Runnable() {            @Override            public void run() {                handler.sendEmptyMessage(1001);                try {                    Thread.sleep(6000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                //子线程 通过Handler 发送消息到主线程的消息队列, 主线程处理该消息                handler.sendEmptyMessage(1001);            }        }).start();        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                handler.sendEmptyMessage(1000);                handler.sendEmptyMessage(1000);                handler.sendEmptyMessage(1000);                handler.sendEmptyMessage(1000);                handler.sendEmptyMessage(1000);                //初始化 Looper                Looper.prepare();                final Handler handler = new Handler() {                    @Override                    public void handleMessage(Message msg) {                        super.handleMessage(msg);                        //子线程                        System.out.println("接收到 what = " + msg.what);                        System.out.println("Thread " + Thread.currentThread().getName());                    }                };                handler.sendEmptyMessage(999);                handler.sendEmptyMessage(9999);                //轮询                Looper.loop();            }        }).start();        //轮询        Looper.loop();    }}

Handler 代码

package android.os;/** * Created by system on 16/9/6. * <p> * 处理和分发消息 * */public class Handler {    final MessageQueue mQueue;    final Looper mLooper;    public Handler() {        mLooper = Looper.myLooper();        if (mLooper == null) {            throw new RuntimeException(                    "Can't create handler inside thread that has not called Looper.prepare()");        }        mQueue = mLooper.mQueue;    }    public void handleMessage(Message msg) {    }    /**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg != null) {            handleMessage(msg);        }    }    public final boolean sendEmptyMessage(int what) {        Message msg = new Message();        msg.what = what;        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            System.out.println(e.getMessage());            return false;        }        msg.target = this;        return queue.enqueueMessage(msg);    }}

Looper

package android.os;/** * Created by system on 16/9/6. * * * 每开启一条线程都应为之创建一个与该线程绑定 Looper 对象 ,以及 MessageQueue 队列 */public class Looper {    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();    private static Looper sMainLooper;  // guarded by Looper.class    final MessageQueue mQueue;    final Thread mThread;    private Looper() {        mQueue = new MessageQueue();        mThread = Thread.currentThread();    }    public static void prepare() {        if (sThreadLocal.get() != null) {            throw new RuntimeException("Only one Looper may be created per thread");        }        sThreadLocal.set(new Looper());    }    public static void prepareMainLooper() {        prepare();        synchronized (Looper.class) {            if (sMainLooper != null) {                throw new IllegalStateException("The main Looper has already been prepared.");            }            sMainLooper = myLooper();        }    }    public static Looper myLooper() {        return sThreadLocal.get();    }    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;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            //分发消息            msg.target.dispatchMessage(msg);        }    }}

Message

package android.os;/** * Created by system on 16/9/6. *  消息 *  由MessageQueue统一列队,终由Handler处理。 */public class Message {    public int what;    /*package*/ Handler target;    /*package*/ Runnable callback;    // sometimes we store linked lists of these things    /*package*/ Message next;}

MessageQueue

package android.os;/** * Created by system on 16/9/6. * * 消息队列,用来存放Handler发送过来的消息(Message),并按照FIFO规则执行 * note:(将Message以链表的方式串联起来的,等待Looper的轮询) */public class MessageQueue {    Message mMessages;// 当前消息    private static final Object lock = new Object();    /**     * 出列 FO (即取出队头的消息)     * @return Message     */    Message next() {        //没有消息时 阻塞        for (; ; ) {            synchronized (this) {                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);                }                if (msg != null) {                    if (prevMsg != null) {                        prevMsg.next = msg.next;                    } else {                        mMessages = msg.next; //成为队头                    }                    msg.next = null; //remove                    return msg;                }            }        }    }    /**     * 消息入列  FIFO     * @param msg     * @return     */    boolean enqueueMessage(Message msg) {        if (msg.target == null) {            throw new IllegalArgumentException("Message must have a target.");        }        synchronized (this) {            Message p = mMessages;            if (p == null) {                // New head, wake up the event queue if blocked.                msg.next = p;                mMessages = msg;            } else {                Message prev;                for (; ; ) {                    prev = p;                    p = p.next;                    if (p == null) {                        break;                    }                }                msg.next = p; // invariant: p == prev.next                prev.next = msg; //成为链尾            }        }        return true;    }}

运行效果图:
这里写图片描述

代码下载

更详细的Android 消息处理机制分析,请看 Android 消息处理机制

1 0
原创粉丝点击