Messenger解析(和Handler、IBinder、Message的关系)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

为了更好的理解bound service利用Messenger来夸进程服务,这里先写一篇文章简单分析下Messenger、Handler、Message、Binder的关系。

先来看看Messenger官方的定义:
Reference to a Handler, which others can use to send messages to it.This allows for the implementation of message-based communication acrossprocesses, by creating a Messenger pointing to a Handler in one process,and handing that Messenger to another process.
Messenger关联一个可以发送消息的Handler。通过指定一个Handler对象创建一个Messenger可以实现基于消息的夸进程通信。

你可以把Messenger理解成一个送信人,他唯一的职责就是送信,即:send(Message msg),来看看send(Message msg)的实现:
发送消息的方法:

public void send(Message message) throws RemoteException {
        mTarget.send(message);
}
焦点关注到mTarget, 看看它是什么东西? send方法又是怎么回事? 和handler有关系?
其实Messenger的源码很简单,只有一个成员变量:mTarget(IMessenger的一个实例),核心就是它了,mTarget在构造方法中产生。
两个构造方法:

public Messenger(Handler target) {
        mTarget = target.getIMessenger();
 }
public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
}
先来说说第一个构造方法(第二个构造方法也许你有些疑惑先放一边,后面解释)。
我们发现,Handler有个getIMessenger()。来看看源码实现:
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);
        }
}

看到这里,我们发现 mTarget 是一个在Handler中的实现的IMessenger实例(IMessenger.Stub 是IMessenger的实现类,里面实现了n多方法,这里不做深究),里面实现了send方法,这个方法调用了Handler的sendMessage方法。看到这里豁然开朗了吧。 mTarget.send(message);其实最终就是Handler。
看到这里,Messenger和Handler的关系很明显了,即: Messenger利用Handler发送消息
上面还有个疑问,第二个构造方法是怎么回事? 
public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
}
Create a Messenger from a raw IBinder, which had previously been  retrieved getBinder。

这是官方解释,即,通过IBinder创建一个Messenger,这个IBinder必须是之前存在的从getBinder()方法中获取的对象

public IBinder getBinder() {
        return mTarget.asBinder();
}
我们把这两个方法放在一起 ,你会发现mTarget(IMessenger)和IBinder存在转化关系,即IMessenger.Stub已经帮我们实现了这种转化方法 asInterface(),IBinder-》mTarget;asBinder(),mTarget-》IBinder。 所以结论是:IBinder可以关联到一个Handler,通过一个Messenger的getBinder()获取的IBinder可以创建一个关联相同Handler的Messager。
 Messenger和Message的关系?
 Message 有个成员:replyTo,它是一个Messenger的实例,它有什么作用呢?我们来看一个例子,在这个例子中我们实现两个线程利用Messenger通信。
一个类:MessengerThread
public class MessengerThread extends Thread {

    private Handler inComingHandler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {

            Log.d("MessengerThread",msg.obj.toString());

            try {
                Message reMsg = Message.obtain();
                reMsg.replyTo = MessengerThread.this.getMessenger();
                reMsg.obj = "reply:hello ,am "+getName();
                msg.replyTo.send(reMsg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }
    };;
    private Messenger messenger;
    private MessengerThread another;

    public MessengerThread(String name) {
        super(name);
        messenger = new Messenger(inComingHandler);

    }

    public void setAnother(MessengerThread another){
        this.another = another;
    }
    public Messenger getMessenger(){
        return messenger;
    }

    @Override
    public void run() {
        if (another != null){
            Message  msg = Message.obtain();
            msg.replyTo = another.getMessenger();
            msg.obj = "hello i am "+getName();
            try {
                another.getMessenger().send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        super.run();
    }
}
测试代码:

MessengerThread messengerThreadA = new MessengerThread("A");
 MessengerThread messengerThreadB = new MessengerThread("B");
 messengerThreadA.setAnother(messengerThreadB);
 messengerThreadB.setAnother(messengerThreadA);
 messengerThreadB.start();
 messengerThreadA.start();
输出:

949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am A
10-11 16:22:36.573    6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am B
10-11 16:22:36.573    6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am A
10-11 16:22:36.574    6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am B
demo地址: https://github.com/liuguangli/MessengerDemo
目录
相关文章
|
JSON 前端开发 数据格式
SpringMVC源码剖析之参数解析器处理handler参数流程
在适用springMVC的时候,通过注解可以很方便的封装请求数据,响应前端数据,很好奇怎么实现的,于是探索一下
|
消息中间件 调度 Android开发
从源码解析Handler机制
从源码解析Handler机制
178 0
从源码解析Handler机制
|
自然语言处理
合同结构化文书解析失败,请联系管理员排查:{"code":3001,"message":"File transform error","success":false,"tracerId":"requestId"}报错处理
在使用自然语言处理自学习平台时,标注任务需要上传标注数据,但是使用doc格式上传文件后开始标注时出现了此提示,此篇文章简单介绍下此问题的处理方式。
724 0
合同结构化文书解析失败,请联系管理员排查:{"code":3001,"message":"File transform error","success":false,"tracerId":"requestId"}报错处理
|
消息中间件 存储 中间件
Watermill(Golang 事件驱动库)Message Router 解析
Watermill(Golang 事件驱动库)Message Router 解析
607 0
Watermill(Golang 事件驱动库)核心部件 Message 解析
Watermill(Golang 事件驱动库)核心部件 Message 解析
454 0
|
消息中间件 存储 Android开发
【Android 异步操作】Handler 机制 ( Android 提供的 Handler 源码解析 | Handler 构造与消息分发 | MessageQueue 消息队列相关方法 )
【Android 异步操作】Handler 机制 ( Android 提供的 Handler 源码解析 | Handler 构造与消息分发 | MessageQueue 消息队列相关方法 )
151 0
|
消息中间件 Android开发
|
消息中间件 机器学习/深度学习 Android开发
Android Handler原理实践解析
前言 Handler消息处理机制在Android开发中起着举足轻重的作用,我们有必要好好理解下其原理,下面我们先从一个简单的例子出发 一、日常使用 假设我们有这么一个需要,请求网络然后将图片展示出来,我们知道网络请求是不允许在主线程执行的,而UI是不能在子线程(具体是不允许在非创建UI的原始线程)...
|
Web App开发 消息中间件 Android开发
Android Handler机制(不含源码解析,适合新手理解)
一、官方解释 A Handler allows you to send and process [Message](https://developer.
1214 0

推荐镜像

更多
下一篇
无影云桌面