Android消息机制

Android消息机制主要指的是Handler的运行机制。
(注意,消息机制中的Handler是android.os包下的Handler,不是java.util.logging包中的Handler,开发中注意不要到错包。)
Handler是消息机制的上层接口。Handler将任务切换到handler所在的线程执行。
与handler相关的有MessageQueue、Looper。其中,
MessageQueue中文名称是消息队列,内部存储了一组消息,并以队列的形式向外提供插入删除操作。MessageQueue以队列的形式命名,而内部实现是单链表。内部提供了next方法读取一条消息,并从消息队列中删除。
Looper是个无限循环,当调用Looper.prepare和Looper.loop方法后Looer就开始工作了。Looper以无限循环方式检查是否有消息,有就处理,无就等待。Looer中有个ThreadLocal对象,用来存储每个线程的数据,通过ThreadLocal可以获取每个线程的Looper,ThreadLocal保证每个线程的数据互不干扰。
流程
Handler创建时,会使用当前线程的Looper来构造内部的消息循环系统。每个Handler对应一个Looper。如果Handler所在的线程没有对应的Looer,则会抛出一个这样的异常信息:

Can't create handler inside thread that has not called Looper.prepare()。 

解决办法就是,在Handler创建之前,调用Looper.Prepare初始化looper,并在handler创建后调用Looper.loop开启循环,若不调用Looper.loop则Looper是无法工作的。
这样的情况一般出现在子线程创建handler对象的时候。为什么主线程我们没有创建Looper对象,却没有抛出这样的异常呢?
原因就是在MainThread中,系统给我们初始化了Looper对象。查看源码可发现这句:

Looper.prepareMainLooper();//创建主线程Looper和MessageQueue
Looper.Loop();//开启主线程Looper

当调用handler.post(Runnable runnable)方法后,会将Runnable对象投递到handler内部的Looer中处理。也可以通过Handler.sendMessage(Message msg)方法来发送一个消息,也是会在Looer中处理。查看源码得知,handler.post方法最终调用的也是handler.send方法来实现的。

当handler.send方法被调用时,它会调用MessageQueue的enqueueMessage将消息存放到MessageQueue中。当Looper检测到时,会调用next方法读取此消息,并从MessageQueue中删除。

相关代码如下:

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

看一下DispatchMessage方法执行流程:
在dispatchMessage方法中有以下几个分支:
先检查Message的callback(是一个Runnable类型的对象)是否为null,如果不为null就执行HandlerCallBack来处理消息;
检查mCallback(是一个CallBack接口类型对象)是否为null,如果不为null,就执行mCallback接口对象的handlerMessage方法来处理消息;
最后则是调用handler的handlerMessage方法来处理消息。

题外话,子线程为什么不能直接访问UI?
android的控件不是线程安全的。在线程中访问ui,可能导致ui不可控。考虑到ui访问效率又不能是主线程阻塞,故不能采用加锁机制。所以在
Android 4.0以后做出了这样的规定,要求子线程不能访问ui,否则会直接抛出异常。异常信息是这样的:

Only the original thread that created a view hierarchy can touch its views.

Handler的应用场景
通常在子线程中将结果发送给主线程,通知主线程更新ui。
也可以在主线程中将任务加入到消息队列顺序执行。

源码分析

//可以直接实现此接口来初始化handler,而不必去实现创建Handler的子类
public interface Callback {
        public boolean handleMessage(Message msg);
    }
//handlerMessage是一个空方法,子类若要通过这种方式处理消息,子类必须自己实现
    public void handleMessage(Message msg) {
    }
//消息处理,分析见上述
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

下面是handler的几个构造方法:

    public Handler() {
        this(null, false);
    }

    public Handler(Callback callback) {
        this(callback, false);
    }
//使用指定的Looper对象构造handler
    public Handler(Looper looper) {
        this(looper, null, false);
    }
    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }
    public Handler(boolean async) {
        this(null, async);
    }

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

 public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

handler的几个构造,由于代码不复杂,这里不再说明。
接下来看一系列的obtainMessage方法,及它们的重载:

//Message.obtainMessage获取的结果是通过Message.Target设置的值
   public final Message obtainMessage()
    {
        return Message.obtain(this);
    }
     public final Message obtainMessage(int what)
    {
        return Message.obtain(this, what);
    }
    public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }
     public final Message obtainMessage(int what, int arg1, int arg2)
    {
        return Message.obtain(this, what, arg1, arg2);
    }
     public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
    {
        return Message.obtain(this, what, arg1, arg2, obj);
    }

接着看几个比较重要的方法:

//post方法与postDelayed方法一样,最终调用的是sendMessageDelayed方法
  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);
    }
    //从消息队列中移除指定的Runnable对象

     public final void removeCallbacks(Runnable r)
    {
        mQueue.removeMessages(this, r, null);
    }
//移除消息队列中的Runnable对象,如果object参数不为null 则会移除所有的
     public final void removeCallbacks(Runnable r, Object token)
    {
        mQueue.removeMessages(this, r, token);
    }

下面是sendmessage的一系列方法,

//将消息添加到消息队列,如果添加成功会返回true,否则返回false
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
//将一个仅有what值的message添加到消息队列,添加成功返回true,否则返回false
    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }

    //在指定的时间后发送一个仅有what值的message,添加到消息队列
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

    //在指定的时间将仅有what值的message添加到消息队列

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        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);
    }
//将消息加入消息队列
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

    //从消息队列中移除指定what值的message
    public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);
    }


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

    public final void removeCallbacksAndMessages(Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }

接下来的代码,是创建了一个IMessager的实现类。可以看出使用了Binder机制。为了实现对使用Messenger跨进程发送消息的处理。涉及到进程通信,这里先不多讲。

final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

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

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

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

    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值