IPC机制

1.前言

此文是在阅读<< Android开发艺术探索 >>的基础上进行总结记录.Android开发中有些场景需要开启多进程.就需要对多进程相关知识系统地了解.自己开车的Demo https://github.com/xwpeng/TestIPC

2.进程相关的adb命令

adb shell ps 查看所有的进程  adb shell ps pid 查看指定pid进程
  adb shell ps | grep 包名 指定包名查看进程信息
  adb shell cat /proc/pid/oom_adj 进程回收建议值

3.几种进程间通信的方式

Android的IPC(Inter-Process Communication/进程间通信),可以使用Binder机制与Socket通信来实现,Bundle的Intent附带数据传递,ContentProvider自带实现了夸进程数据共享。Android的ShareUID模式可以使两个具有相同shareUID并且签名相同的应用共享数据(data目录,组件信息,内存数据),他们看起来就像一个应用的两个部分。

4.多进程带来的问题

系统在创建新的进程会分配独立的虚拟机,相当于启动一个应用,创建新的Application。所以,不同进程会拥有独立的虚拟机,Application以及内存空间。一个应用的多进程模式可以理解为多个应用采用了ShareUID模式。
  具体造成的影响:

  1. 静态成员和单例模式完全失效。
  2. 线程同步机制完全失效。
  3. SharedPreferences不可靠.用ContentProvider包装过的SharePreferencesDPreference,多进程下可靠.
  4. Application创建代码多次执行,每增一个进程,相当于启动一个应用,分配独立的虚拟机与内存。

5.开启多进程

Android中只能通过给四大组件设置android:process来开启多线程,无法给一个实体类或者线程指定进程,代码运行在哪个线程,取决于调用代码的组件.进程名以":"开头的为私有进程,其他为公有进程,公有进程可以使用ShareUID方式运行其他相同签名应用的组件(很少用).

6.序列化

Intent与Binder传递数据需要先进行序列化.
  serializable是Java的序列化实现,用于对象与存储设备的读取保持,使用简单,大量I/O操作开销大.serializable需要指定serialVersionUID,默认使用实体类的hash值.如果不指定serialVersion,当类进行改动,hash变化,就会造成反序列化失败,程序Crash.
  静态成员变量属于类不属于变量,不参与序列化.transient关键字标记的成员变量不参与序列化.
  Parcelable是android特有的,使用起来麻烦,主要是在内存序列化,效率高。

7.AIDL

参考http://www.jianshu.com/p/c6a8e913efb3
  值得注意的是:客户端发请求调用transact方法,由服务端的onTransact来响应,客户端发起远程请求的时候线程会挂起,等待服务端返回数据才继续执行,不会异步。需要确定这个远程请求是否耗时,再决定是否再主线程做远程请求.
  如果你的aidl接口有引用到实体类,实体类要实现Parcelable,并且需要创建实体类xxx.aidl,引用实体的其他aidl文件需要import.添加实体类.aidl要注意路径必须与java目录下的路径完全一致.比如实体类Book是在./java/应用包名/entity/Book.java,在aidl下也得新建完全一直的目录结构./aidl/应用包名/entity/Book.aidl.见Demo:https://github.com/xwpeng/TestIPC User2.java
  如果客户端有多个同时操作服务端数据集合,服务端需要考虑线程同步.CopyOnWriteArray与ConcurrentHashMap支持自动的线程同步.服务端集合可以使用它们解决这个问题.
  AtomicBoolean,判断与set新值组装成原子操作,避免多线程并发问题.
  AIDL接口回调实现服务端调用客户端接口,比如有新消息来时推送.大家都知道,一个Activity实现某接口,将此接口传递到其他类中由其他类调用,这是面向接口编程.在AIDl中是怎么实现这中策略的呢.

  1. 客户端调服务端代码是定义一个AIDL接口,由服务端实现,然后在bind的回调中返回给客户端.如果在这个接口中定义方法能够将另一个AIDL接口A传给服务端,客户端实现A接口,那么服务端就能通过此接口方便的调用客户端接口.在Demo中IOnNewBookArrivedLIistener与NewBookReceiverActivity展示了这种用法.
  2. 服务端管理客服端接口要使用RemoteCallbackList,不然无法解绑客服端的推送.原因是:当客服端的书籍提醒接口实现实例通过AIDL接口方法传递到服务端会变成一个新的对象,用一般的List管理客服端接口在添加的时候添加的是新的对象(同一方法参数的新旧对象在AIDL中有一一对应的关系,这就是为什么服务端调用新对象的方法,客服端旧对象能够响应,猜测,TODO),解绑方法的参数,传递到服务端也是一个新的对象.这就造成接口管理List找不到注册时添加的接口,造成解绑失败.而RemoteCallbackLis是系统专门提供的用于跨进程listener的接口.工作原理是用一个Map结构存储接口.同一客户端跨进程传输参数服务端会产生新对象,但是它的底层Binder对象是不会变的,所以可以用它作为key来标识客户端,value则是客服端接口.且客服端挂了会自动移除相应键值对,自动支持线程同步.beginBroadCast和finishBroadCast必须配对使用.
  3. 如果服务端不使用RemoteCallBackList管理回调接口,发现先由MainActivity绑定PushService,再启动NewBookReceiverActivity的AIDL接口会被不断的回调,即使已经调用了Destroy().弄不明白为什么会这样,TODO.
      push进程挂掉监听.
      权限验证,在onTransact中调用,注意不要在onBind中判断权限.

8. Messenger

Messager本质是对AIDL进行封装.
  参考http://www.jianshu.com/p/253e424c377f
  梳理我demo的思路,程序设计首要是思路清晰

Messenger通信

  这种方式是利用Handle消息队列互传消息,意味着这种方式是串行的.同时无法直接调用其他进程的方法,只能根据收到的消息来调用方法.返回值也只能用消息传递

9.in/out/inout参数标记探索

参考你真的理解AIDL中的in,out,inout么?
  注意Book类的序列化需要添加,这个用Android-stuido自动实现接口是没有的,而在传输过程需要调用readFromParcel方法,没有将报错.见Demo:https://github.com/xwpeng/TestIPC Book.java

protected Book(Parcel in) { 
readFromParcel(in); 
}  

public void readFromParcel(Parcel in) {
 id = in.readInt(); 
name = in.readString(); 
price = in.readDouble();
 }

总结:

  1. in表示服务端将接收传入的参数(Book book).服务端对接收到参数(book)做修改,客户端不会同步修改book;
  2. out表示服务端将不接收传入的参数(Book book),从源码看是新new了一个对象.服务端对接收到参数(book)做修改,客户端会同步修改book;
  3. inout表示服务端接收传入的参数(Book book.服务端对接收到参数(book)做修改,客户端会同步修改book.

10.TCP实现进程通信

见demo https://github.com/xwpeng/TestIPC

11.Binder管理(连接池)

我们希望在一个远程进程中处理很多不同的业务(实际场景没有遇到过),假设需要在远程进程中处理计算与安全中心业务。常规的做法是开2个service,这2个serivce跑在同一个进程中。现在想只用一个service就能处理很多不同的功能。
  声明IBinderPool.aidl,有方法Binder queryBinder(int code)。在连接完Service后,得到IBinderPool型的Binder对象,传入定义好的code调用此对象的queryBinder得到对应的业务aidl的Binder对象。
  用单例类将连接service,请求得到binder管理起来,完成一个实例一个连接能返回多个binder的目的。

IPC方式对比

  • Intent,Bundle:  简单易用,单向,多用于四大组件传递初始数据,最多数据量1M
  • 文件交互:  不支持多并发,操作麻烦,局限性大
  • Socke:t  功能强大,双向通信,实现与维护困难,多用于网络通信
  • ContentProvider  适用于数据提供,数据源共享,不适合数据交互与RPC(远程过程调用)
  • Messenger:  实现简单一对一还好,并发处理困难,RPC困难
  • AIDL:  功能强大,拓展性强,支持多并发,需要处理好线程同步,支持RPC
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,711评论 18 139
  • 一、Android IPC简介 IPC是Inter-Process Communication的缩写,含义就是进程...
    SeanMa阅读 1,834评论 0 8
  • Android开发艺术探索 第二章IPC机制 Linux中IPC通信方式?答:命名管道,共享内存,信号量(具体再细...
    方木Rudy阅读 1,099评论 0 2
  • 原文:http://weishu.me/2016/01/12/binder-index-for-newer/ 要点...
    指尖流逝的青春阅读 2,610评论 0 13
  • 孝文帝刘恒是一代盛世的铺路者,他本来是没有机会登上皇位的,但因为吕后的种种行为,以至于人人皆愤,而恰好他品...
    雾起夜续阅读 356评论 0 7