}

}

break;

default:

super.handleMessage(msg);

break;

}

}

}

}

工程中的一个独立进程客户端client代码:

public class MainActivity extends Activity {

private TextView mTextView;

private Messenger mRemoteMessenger = null;

private Messenger mClientMessenger;

private ClientHandler mClientHandler;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView) findViewById(R.id.content_show);

//

mClientHandler = new ClientHandler();

mClientMessenger = new Messenger(mClientHandler);

bindService(new Intent(this, RemoteService.class), connection, Context.BIND_AUTO_CREATE);

}

@Override

protected void onDestroy() {

super.onDestroy();

unbindService(connection);

}

private ServiceConnection connection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

mRemoteMessenger = new Messenger(service);

//注意obtain第一个参数,前面文章有解释

Message message = Message.obtain(null, RemoteService.MSG_TAG_REMOTE);

message.replyTo = mClientMessenger;

try {

mRemoteMessenger.send(message);

} catch (RemoteException e) {

e.printStackTrace();

}

}

@Override

public void onServiceDisconnected(ComponentName name) {}

};

private class ClientHandler extends Handler {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case RemoteService.MSG_TAG_CLIENT:

if (mTextView != null) {

mTextView.setText(msg.arg1+"");

}

break;

default:

super.handleMessage(msg);

break;

}

}

}

}

看着了吧,这就是一个超级简单的Messenger使用场景,具体过程比较形象的描述如下图:

相信有了这幅图就不需要再解释啥了吧,这个也够明白了。

【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】

3 Messenger源码浅析


通过上面的实例明显可以看出,在不考虑并发的情况下,Messenger相比AIDL无论从代码量、工程结构、复杂度等上都更加胜出一筹。既然这么好用的东东,那就来看看他的源码吧,如下我
们先通观一下Messenger类的整个核心代码,然后再细说。如下所示:

/**

  • 关联Handler进行跨进程收发消息的信使管理桥梁类

  • 可以看见Messenger就是一个信使,就是一个Object

*/

public final class Messenger implements Parcelable {

//其实就是远程的MessengerService的AIDL接口

private final IMessenger mTarget;

//创建一个指向target Handler的Messenger,然后调运Messenger的send就像Handler的sendMessage

public Messenger(Handler target) {

mTarget = target.getIMessenger();

}

//跨进程发送消息,通常用Message.obtain()填充message参数,也可以自己new

public void send(Message message) throws RemoteException {

mTarget.send(message);

}

//获得Messenger的Binder,一般用在remote端获取返回

public IBinder getBinder() {

return mTarget.asBinder();

}

//如果两个Messenger相等则表明指向了相同的Handler

public boolean equals(Object otherObj) {

if (otherObj == null) {

return false;

}

try {

return mTarget.asBinder().equals(((Messenger)otherObj)

.mTarget.asBinder());

} catch (ClassCastException e) {

}

return false;

}

//获取getBinder相同的Messenger对象,一般用在client端获取

public Messenger(IBinder target) {

mTarget = IMessenger.Stub.asInterface(target);

}

}

通过上面全局预览Messenger类及上面的实例使用相信你一定注意到了Messenger有两个构造函数,分别是public Messenger(Handler target)和public Messenger(IBinder target),很明显你已经知道了,参数为Handler的是远程进程实例方法,而参数为IBinder为客户端进程的实例方法。既然这样那我们就先从服务端获取Messenger对象的构造函数public Messenger(Handler target)说起吧,可以看见代码如下:

public Messenger(Handler target) {

mTarget = target.getIMessenger();

}

该构造函数调运了Handler的getIMessenger方法,这个方法在Handler中源码如下:

public class Handler {

//其实对于一个Handler对象来说getIMessenger得到的Messenger是一个单例模式对象

final IMessenger getIMessenger() {

synchronized (mQueue) {

if (mMessenger != null) {

return mMessenger;

}

//单例模式得到Messenger实现类MessengerImpl对象

mMessenger = new MessengerImpl();

return mMessenger;

}

}

//可以看见这其实是Messenger的AIDL实现

private final class MessengerImpl extends IMessenger.Stub {

public void send(Message msg) {

//send方法真正调运了Handler的sendMessage实现发送消息

Handler.this.sendMessage(msg);

}

}

}

可以看见,getIMessenger对于每一个Handler对象来说是单例的对象,而且这个IMessenger对象的实现类是MessengerImpl,也可以看见MessengerImpl又是IMessenger.Stub的实现类,这个IMessenger.Stub其实就是AIDL文件通过aapt自动生成在我们gen或者build目录下的服务端接口子类而已。那既然这么说了我们就来确认下吧,看下面这个AIDL文件(frameworks/base/core/java/android/os/IMessenger.aidl):

package android.os;

import android.os.Message;

/** @hide */

oneway interface IMessenger {

//可以看见,上面的MessengerImpl就实现了Messenger远程的send接口

void send(in Message msg);

}

这下明白了吧,Messenger类中的mTarget其实就是一个Handler中单例的IMessenger远程IPC接口MessengerImpl。

紧接着我们看下Service中的onBind实现,其调运了Messenger的getBinder方法,这个方法源码如下:

public IBinder getBinder() {

s;

import android.os.Message;

/** @hide */

oneway interface IMessenger {

//可以看见,上面的MessengerImpl就实现了Messenger远程的send接口

void send(in Message msg);

}

这下明白了吧,Messenger类中的mTarget其实就是一个Handler中单例的IMessenger远程IPC接口MessengerImpl。

紧接着我们看下Service中的onBind实现,其调运了Messenger的getBinder方法,这个方法源码如下:

public IBinder getBinder() {

Android应用进程间通信之Messenger信使使用及源码浅析,Android插件化入门指南相关推荐

  1. Android应用进程间通信之Messenger信使使用及源码浅析

    转载: http://blog.csdn.net/yanbober 1 背景 这个知识点是个low货,刚开始其实想在之前一篇文章<Android异步消息处理机制详解及源码分析>一文中作为一 ...

  2. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  3. 【Android 安装包优化】WebP 应用 ( libwebp 源码下载 | Android.mk 和 Application.mk 构建脚本修改 | libwebp 函数库编译 )

    文章目录 一. libwebp 源码下载 二. libwebp 源码编译脚本修改 三. libwebp 函数库编译 四.参考资料 一. libwebp 源码下载 Google 提供了一系列的 WebP ...

  4. Android插件化入门指南,系列篇

    在面试程序员岗位时,我们往往需要经历一个编程面试过程,雇主会借此考验面试者的技术实力.然而,这些技术问题有时候却和我们的实际工作并无太大关系,也由此可能给我们的编程面试准备阶段带来很大的压力.我也因此 ...

  5. Android 仿钉钉、微信 群聊组合头像,Android插件化入门指南

    简介: Android 仿钉钉.微信 群聊组合头像 更多:作者   提 Bug 标签: 效果预览 | | | |   | | - | - | - | - | | | | | | | | | | | 功 ...

  6. oppo安卓面试题,Android插件化入门指南,含泪整理面经

    最近很多人说,Android越来越不好找工作了,学习NDK开发会不会好点,今天就聊聊这个问题.是否应该选择学NDK? 1.哪些场景下要用到NDK开发? 跨平台的库,如FFmpeg, skip,weex ...

  7. 看完99%的人都学会了!Android插件化入门指南,BAT大厂面试总结

    程序员与别的专业有所不同,其他专业都是越老越香,而程序员却是一个例外,因为计算机技术更新太快,而且工作强度很大,因此大部分程序员只会写 3 年代码.3 年后要不晋升做项目经理,要么转行,个别研究所除外 ...

  8. 结合源码探讨Android系统的启动流程

    结合源码探讨Android系统的启动流程 由于本人能力有限,所考虑或者疏忽错漏的地方或多或少应该存在.同时,Android从启动过程开始,实际上就涉及多个技术难点和多种通信机制的知识点. 基于上面两个 ...

  9. 【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )

    文章目录 安卓直播推流专栏博客总结 一. RTMP 协议 二. RTMP 协议使用 三. RTMPDump 源码下载 四. RTMPDump 源码交叉编译 五. RTMPDump 源码导入 Andro ...

最新文章

  1. 2018年终总结之摄影作品展
  2. 三角剖分(delaunay)拓扑结构 高维近邻
  3. Windows下更改pip镜像源
  4. 在Java内部类中使用外部类的成员方法以及成员变量
  5. 2022大厂面试必问要点总结
  6. android mimetype类型,如何确定android中的MIME类型?
  7. unable to recognize ole stream是什么意思_洞彻状态管理,或者说为什么你永远做不到...
  8. FFPLAY的原理(三)
  9. 转移服务器显示乱码,两台服务器之间数据传输乱码问题
  10. RAW socket使用
  11. 服务器记事本找回文本,如何还原记事本中已删除的内容
  12. Sketch教程|如何访问组件视图?
  13. 为什么一提到苹果就想到乔布斯,蒂姆·库克的事迹你知道多少?
  14. 极具发展潜力的20项油气勘探开发新技术
  15. python软件如何下载-Python怎么下载安装
  16. ABB机器人的几种停止指令详解
  17. Win7安全模式卡在ClassPNP sys位置解决办法之一
  18. 汽车matlab小论文,基于matlab汽车道路模型研究论文
  19. windows下安装speedtest的经历和问题
  20. 安卓沉浸式状态栏,android沉浸式状态栏工具类封装

热门文章

  1. c语言炉石传说算法设计,FZU Problem 2232 炉石传说(匈牙利算法)
  2. linux程序制作文件,Linux编程实现制作文件的ed2k链
  3. 教你win10系统显卡驱动安装失败的解决方法
  4. Vue 高频面试题总结05 内附答案
  5. c语言真随机,怎样让c语言中的随机函数真正随机?
  6. 如果电脑技术最初是中国人发明的,那现在编程是不是就是中文的?
  7. 阿里云服务器Windows Server 2008 架设 Web 服务器教程(图文详解)
  8. STM32学习笔记-L298N驱动模块-电机
  9. 常见编程命名方法,看看你属于哪一种?
  10. 小爱音箱mini接入HA,并且通过Node-RED来控制小爱说话