Android消息机制 java常用类

来源:互联网 发布:网络星光大道张卫 编辑:程序博客网 时间:2024/06/09 21:48

消息驱动是一种进程或线程的运行模式。内部、外部的各种事件可以放到消息队列中按序处理。比如:Android的应用UI线程。


在windows的消息处理模型中,只有一个系统消息队列,这个队列是整个进程的核心,几乎所有动作都要转换成消息,放到这个队列中,消息处理在主线程完成。

也就是有多个线程发送消息,只有一个属于进程的消息队列,以及只有一个主线程处理消息队列中的消息。


Android的消息处理不一样。Android没有全局的消息队列,消息队列是和某个线程相关的。每个线程最多只有一个消息队列,消息的取出和处理也在线程中完成。

也就是有多个线程发消息,有多个消息队列在不同的线程中,分别在各自的线程中处理消息。


Windows的消息模型比较简单,但是全局的消息队列容易成为程序的瓶颈。


Looper类

looper是线程的消息循环处理器,每个线程只能有一个Looper对象,其内部有一个MessageQueue,所有消息都存放在这个队列中。新创建一个线程时,系统不会为这个线程创建Looper,需要自己创建。Android在启动时,为主线程(UI线程——创建了一个looper对象)。

我们先看一下HandlerThread线程,其就是继承了一个普通的线程,提供了一个消息队列和消息相应代码的运行环境。

public class HandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }        public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }        protected void onLooperPrepared() {    }    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();//Looper类的实例必须通过prepare函数创建        synchronized (this) {            mLooper = Looper.myLooper();//通过myLooper方法获取Looper对象            notifyAll();        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();//loop函数主要分发消息队列中的消息。        mTid = -1;    }        public Looper getLooper() {        if (!isAlive()) {            return null;        }                // If the thread has been started, wait until the looper has been created.        synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }    public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }}

下面我们主要看下Looper类中的loop方法:

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;//消息队列        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        for (;;) {//无线循环            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }........            msg.target.dispatchMessage(msg);//分发消息......            msg.recycle();        }    }


Handler类

Handler主要负责消息的发送和处理。在一个线程中可以只用一个Hander对象处理所以消息,也可以使用多个。

构造一个Handler对象,需要两个参数,线程的Looper对象和消息处理函数,如果不指定looper,会使用当前线程的looper对象

Handler发送消息的接口如下:

    public final boolean sendMessage(Message msg)//不插队    {        return sendMessageDelayed(msg, 0);    }    public final boolean sendEmptyMessage(int what)//只有一个消息ID    {        return sendEmptyMessageDelayed(what, 0);    }    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageDelayed(msg, delayMillis);    }    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {        Message msg = Message.obtain();//指定时间,只有消息ID,其实就是自己获取一个msg,再调用sendMessageAtTime        msg.what = what;        return sendMessageAtTime(msg, uptimeMillis);    }    public final boolean sendMessageDelayed(Message msg, long delayMillis)//延迟多少时间    {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }    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);    }    public final boolean sendMessageAtFrontOfQueue(Message msg) {//非常紧急,希望尽快处理        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, 0);    }    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {        msg.target = this;//注意msg.target都是handler,因此在消息线程的loop函数处理消息时,msg.target.dispatchMessage会回到handler。        if (mAsynchronous) {            msg.setAsynchronous(true);        }        return queue.enqueueMessage(msg, uptimeMillis);    }

所有的发送消息接口,最后都会调用MessageQueue类中enqueueMessage函数,参数除了消息外,就是一个时间。而MessageQueue类中enqueueMessage函数只是把消息插入到消息队列中的合适位置。

我们再来看看Handler类的一些Post类型的函数:

    public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }        public final boolean postAtTime(Runnable r, long uptimeMillis)    {        return sendMessageAtTime(getPostMessage(r), uptimeMillis);    }    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)    {        return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);    }    public final boolean postDelayed(Runnable r, long delayMillis)    {        return sendMessageDelayed(getPostMessage(r), delayMillis);    }        public final boolean postAtFrontOfQueue(Runnable r)    {        return sendMessageAtFrontOfQueue(getPostMessage(r));    }

也是调用的send函数,只是调用了getPostMessage函数:

    private static Message getPostMessage(Runnable r) {        Message m = Message.obtain();        m.callback = r;        return m;    }

创建了一个message对象,并且将Runable对象赋给了callback。

下面再来看看Handler对象的dispatchMessage就知道了:

    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);//如果msg自带了callback函数        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);//最后再调用Handler的handleMessage函数        }    }

看看handleCallback函数就是调用了msg的回调函数:

    private static void handleCallback(Message message) {        message.callback.run();    }

Handler中removeMessages将消息队列中的消息去除:

    public final void removeMessages(int what, Object object) {        mQueue.removeMessages(this, what, object);    }


最后总结下:首先消息机制需要一个线程环境,里面需要一个Looper对象,并且在线程的run函数中调用Looper.loop()函数。函数需要一个handler来发送和处理消息。Hander要有一个Looper对象,来指定其线程,还要实现handleMessage函数。











1 0
原创粉丝点击