Android消息机制 java常用类

消息驱动是一种进程或线程的运行模式。内部、外部的各种事件可以放到消息队列中按序处理。比如: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函数。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值