android 线程间通讯

来源:互联网 发布:2017网络流行舞蹈 编辑:程序博客网 时间:2024/06/04 18:33

在巨人的基础上,做了些修改,加了自己的理解。

在handler的简单用法中,我们自己简单new出一个handler 然后调用它的sendMessage方法发出一条消息。然后在handler类重写了handler的handlerMessage方法来进行处理。看似就是这么简单的俩步,其实背后隐藏了很多我们不知道的流程。

   在介绍这个之前,我先介绍几个概念

  1。Message 这个应该很清楚吧 就是我们发送的消息 介绍一个里面的一个方法Message.obtain函数。作用是从Message Pool中取出一个Message,如果Message Pool中没有Message可取则新建一个Message返回。 message Pool 这个变量在Message类的声明如下:

 private static Message mPool;

可以看到就是Message本身,由此可知,Message已经实现了队列的功能。


2.MessageQueue

顾名思义就是消息队列,主要是管理Message,比如下面一个方法

final boolean enqueueMessage(Message msg, long when)  这个方法就是用来将message放入队列中。

final Message next() {}获取下一个message


3。Looper

我暂且叫他循环体吧。其实就是个while循环,不断的从MessageQueue中读取消息,然后交给handler处理

关键代码在public static final void loop()里面


4.handler 当然就是用来发送和处理消息。


下面我就把这个四个联系起来,看看他们在内部到底怎么执行。


首先通过handler发出一条消息,发到哪呢 肯定是MessageQueue里,最终会调用MessageQueue的 enqueueMessage函数,enqueueMessage根据上面的接收的将接收的message放入队列中。

通过Loop从MessageQueue中从前往后取出Message(通过 MessageQueue的方法 next()),然后通过Handler的dispatchMessage函数进行消息的处理(可见消息的处理是Handler负责的),消息处理完了以后通过Message对象的recycle函数放到Message Pool中,以便下次使用。通过Pool的处理提供了一定的内存管理从而加速消息对象的获取。至于如何处理就看你的handler如何定义了由你指定(三个方法,优先级从高到低:Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;Handler里面的mCallback指向的一个实现了 Callback接口的对象,里面的handleMessage进行处理;处理消息Handler对象对应的类继承并实现了其中 handleMessage函数,通过这个实现的handleMessage函数处理消息)。

  大致流程就是handler------->>发送message---->>MessageQueue

Looper--->从messagequeue中取出message----->>在触发handler的消息分发函数----调用handler中定义的方法.


这里有个疑问那looper 和messagequeue什么时候生成呢。其实messagequeue在Looper创建的时候就生成了。那Looper什么时候生成呢?其实Looper是跟一个线程关联的。而主线程会自动调用Looper类里的prepareMainLooper()方法,生成自己的Looper,但其他线程则不会自己创建了。待会再说。


  先来看看我们上次的简单handler例子。这下应该知道他们内部的流程了吧。其实我们在Hander handler=new Handler();其实就已经把主线程的Looper关联上来了,有了Looper我们也就有了MessageQueue,Looper的构造函数可以看出来。

private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

所以我们在调用sendMessage的时候就把这个Message发送到由Looper创建的MessageQueue里。Looper有主线程创建的,当然消息会在主线程处理了。这样就实现了简单的子线程到主线程的通信了。给我的感觉就是MessageQueue就是线程通信的桥梁。


那好,如果现在我要创建子线程的Looper呢 然后怎么把这个Looper绑定Handler上呢。其实很简单 在子线程调用Looper.prepare()就可以创建子线程的Looper

public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

然后通过Looper.myLooper()就可以拿到这个Looper对象,最后就是把这个Looper 跟Handler绑定起来。其实在构建handler对象的时候我们除了我默认无参构造方法(这个就是我们上次那个例子用的)还有有参的构造方法,就是传Looper的。好了,这样就可以把Looper跟Handler绑定起来了。这你在主线程调用Handler.sendMessage就是把message发到子线程里来了。这样就实现主线程到子线程的通信了。


总结:有了线程A,若需与其他线程,,例如跟B交互,则需要looperA,于是就有了MessageQueueA,handlerA需绑定looperA,再有了handlerA。


线程B使用handlerA发送消息Message给A,handlerA将message交给MessageQueueA处理,MessageQueueA将message放到message pool里面,

此时looper检测到有了新的message,于是将message又交给了handlerA,handlerA又将message交给了线程A的回调函数,于是A得到了message,绕死人了!!!


若有不对之处,希望指出。

原创粉丝点击