Android 多进程编程 15问15答!

ps:阅读本文 需要对android 多进程编程有一定了解。

1.Android中总共有几种方式进行IPC?

答:一共有两种,一种是binder 还有一种是socket。Binder 大家用的比较多。Socket很少有人用,这里给出一个利用Socket进行ipc通信的例子。

服务端代码:

客户端代码:

最后看一下运行效果:

2.android:process 属性值的书写有什么讲究?

答::remote 这种写法 其实就等于 包名:remote 而且这种写法 属于当前app的私有进程, 其他app 不可以和这个进程跑在一起的。

如果是直接 把android:process 写成字符串形式的话, 那这种进程就是全局进程了,谁都可以用。哪怕是其他app 只要是shareUid一样

就可以和这个进程跑在一起。当然了,签名也必须一样!

 

3.多进程编程的时候 我们需要注意哪些坑?

答:一定要记住 多进程的时候 实际上 一个进程就是一个虚拟机,所以 会引发如下几个问题:

a:所有静态变量和单例模式之类的 全部没用了。因为你多进程么,假设你的app代码里面 开启了2个进程,同时你的代码里面 有一个静态变量,这个时候注意 你的静态变量虽然在代码里只有一份,

但是此时是2个进程在跑 ,有2个虚拟机,所以你这个静态变量也是会变成两份的!

b:SharedPreferences 会失去同步效果。因为sp这个东西 你们看下源码就知道了,实际上他的底层就是个xml。。。并且android 对这个xml的读写自己弄了一套缓存,注意这个缓存是运行在内存中的,

所以你就知道 一旦多个进程的话,这个缓存就是多份了。。。。所以记住 不要在多进程里面使用sp

c:Application 会创建多次。这个你们打下log就知道了,所以如果你们application 有特殊处理的话 记得考虑下多进程的情况。

上面3个是我们需要注意的点,其实也很好理解,对于同一个app的 多个进程来说 ,他就等于 多个app 在运行,只不过这些app的uid和签名都一样!你想明白这点 就懂了android 多进程了。

 

4.android中有哪几种序列化方式?分别要注意什么?

答:两种。Serializable和Parcelable

Serializable:这种方式 就是要注意serialVersionUID,一般ide 给你生成的值 都是根据你class的结构来做的,假设你在版本1.0.1 里面 创建了class A,并且序列化了一个对象a 在sd卡里。

过了一段时间 你在1.0.2 版本里 把A的代码 改了很多,此时ide 会把你的serialVersionUID 值也随之改掉。那如果你在1.0.2版本里 还想反序列化这个对象a的话 就会出错了。

所以serialVersionUID 就是一个记录class 版本号的标示,我们最好还是把他写死。。。。这样不会影响我们的客户端。此外 transient 这个标记的变量也不会被序列化。

Parcelable:write方法就是序列化的时候 执行的方法 creator 就是反序列化的过程。Intent bundle bitmap 都实现了这个接口。List Map 也可以序列化 提前是 元素是这个接口对象。

两者基本上是差不多的,只不过Parcelable效率更高,一般在内存中使用时 我们用Parcelable,如果是 序列化到本地或者网络 这种流里的时候 我们就用Serializable 因为比较方便。

 

5.当遇到一个数据 无法放在Bundle里时,如何进行进程间通讯?

答:假设我们有一个需求,让A进程 计算一个东西以后 把 结果 result 传递给B进程。但是这个result结果 没有实现Parcelable 接口也无法放在bundle里。此时 该如何传递这个result到B?

其实可以让A进程 启动B进程 的一个intentService。让这个service 去计算出来这个结果result,这时候 我们会发现 此时这个service和b进程 在一个进程里。 result当然就随便传递了。不需要ipc来传递

 

6.Messenger 使用时,要注意哪些,他的原理是什么?

答:原理的话 其实看一下 源码就知道了:

一看到这个代码我们就明白 原理就是AIDL么。要注意的话 就是Messenger只能用于单向通信,不能用于双向的 。如果你要用双向通信并且还要用Messenger来完成的话  就必须用2个Messenger。

Messenger传递对象就是传递的Message对象。其中我们注意了,在进程通信的时候,Message里的object 字段 只能传递 系统的parceable对象。也就是intent bitmap 这种系统自己实现的parceable接口对象。

如果是我们自己写的parceable 是无法放在object里面 用于进程通信的,如果你要用,请放在bundle里。此外Messenger 在内部 是串行处理请求的,大量消息 一起发给服务端这种业务模型

最好就别用Messenger了。直接自己写一个AIDL 最合适。

 

7.使用AIDL的时候 有哪些注意事项?

答:有下面几个注意事项:

a:aidl文件里不是所有数据类型都可以使用。只支持 基本数据类型,string,charSequence,List(只支持ArrayList,且里面的元素都能被AIDL支持),Map(只支持hashMap,并且元素必须是AIDL支持的),Parcelable,AIDL自己。

b:自定义的parceable对象要在aidl中 import 进来。并且自定义的parceable 要在aidl里 也额外声明一下,具体的看我前面的那篇blog即可。

c:aidl 里面只能写方法 不能写静态常量。

 

8.in out inout 这三个参数 在aidl 到底有啥用,不写有什么危害么?

答:据我观察 你不写其实没什么危害,但是你写明白了 传输效率会增加。其实这3个参数很好理解,简单建立一个方法模型:

假设你的aidl文件里有一个方法  void addPerson(Person person),这方法一看 就是客户端传一个person 到服务端 所以这个地方参数就是in。

如果你有一个方法叫 void getList(List a) 你看这个方法 就是把服务端的list 传递给这个参数a的list 那你就把参数写成out即可。

inout 就更好理解了,实际就是 void modifyList(List b),意思就是 先把b 这个list 传递给服务端,然后还要修改这个list。

 

9.CopyOnWriteArrayList 可以在aidl中使用吗?为什么?

答:可以使用。

虽然看声明 他并没有实现Parceable这个接口。也不是ArrayList的子类,但实际上AIDL支持的是抽象的List,所以在底层的时候 Binder 会把CopyOnWriteArrayList

转换成ArrayList 传递给客户端的。ConcurrentHashMap 也是一样。

 

10.Android 进程通信时候 能传递对象吗?

答:严格意义上 是不能的,实际上binder 会把客户端传递过来的对象 重新转换为一个新的对象 传递给服务端。对象的跨进程传输 本质上就是序列化和反序列化的过程。

 

11.RemoteCallBackList 干嘛的?使用时注意哪些?

答:具体可看http://www.cnblogs.com/punkisnotdead/p/5158016.html。 实际上这个东西讲明白了 就是用于 android中管理 跨进程listener接口的。

你想明白这个道理 就都懂了。而且他特别方便的是,客户端进程终止以后 他可以自动删除listenr。使用注意点就是begin和finish要成对出现。就算你是遍历listenrer操作

也要用这2个方法

 

12.aidl运行时的 线程模型?

答:http://www.cnblogs.com/punkisnotdead/p/5163464.html 这篇分析binder代码的时候 已经讲的很清楚了。这里再总结一次。

client 调用 server的方法a,client本身是会挂起的, 会一直等待server的方法a的 执行结果。

同时这个方法a 是运行在binder线程池中,所以server的方法  可以执行耗时操作。只不过 client调用的server方法时

注意不要在ui线程里调用,不然会anr的。同时如果你的业务是 一个server 多种client ,那你的server端 方法 要支持同步,不然会数据错乱的!

 

13.服务端 调用 客户端listener 方法有什么讲究?

答:实际上 和12问题是一样的,server 想调用 client的方法b,b也是会执行在 client所属进程的 binder线程池内的。同时我们也要避免 如果方法b执行时间很长,

记得server调用的时候 不要在主线程里调用。此外我们一般client 都是在activity里,记得 listener调用的方法 如果涉及到ui,请用handler切换到ui线程来做。

 

14.如何做权限认证?

答:两种方法,可以在onBind里 检查权限,也可以在server的onTransact里验证,验证失败返回false即可。后者方法更好 还可以验证uid pid等 可以支持复杂的多进程业务模型,

尤其是安全相关的。

 

15.一个aidl 就必须对应一个service吗?多种aidl 是不是只能多个service?

答:不是的,aidl 只不过是帮你书写binder用的工具,你当然可以只启动一个service 但是对应多个binder。要知道 service 资源是有限的 假设你app复杂 10个业务 开启10个service

那不是就乱套了。完全可以只开启一个service 但是这一个service 可以控制多种aidl 对应的binder,你要用哪个 就取那个binder 即可。

下面给出实例。

首先看一下 代码结构和运行效果,实际上就是一个加法binder 和一个乘法binder 只不过 这2个binder 都由一个service来控制而已。

365799-20160129135657521-340132331

然后来看一下加法和乘法的 aidl以及对应的binder 对象:

然后看看我们最为关键的binder manger 如何设计:

最后看一下 我们的clinet端:

1 7 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部