最近突然写了很多文章,觉得自己对android系统和java知识也是进行了深层次学习,也趁着这段时间更加成长。以后也会继续学习,继续写博客。
IPC
IPC就是进程间通信,体现在以下几个方面
- Windows中的剪切板,管道,邮槽
- 管道(从百度百科我们了解到大概是这样的,Linux任何事物都视为文件,就是一个特殊文件,一个进程向这个文件写数据,而另一个进程则在文件中读取数据,其他问题我们不考虑)
- 共享内存(共享单车用过没?大概差不多,既然共享了更新会及时的)
- 信号量(也叫信号灯,同步用的,一个线程完成操作了就通过信号量告诉另外一个线程进行操作,信号量可以为红灯/黄灯/绿灯.....)和互斥量(我们平常用的锁,互斥用的,一个线程占用了资源,另外的线程就不能访问,只能为解锁/上锁)有区别
- 套接字(TCP/IP的封装)
android中的IPC通信
- Bundle(实现Parcelable接口)
- 文件共享(sharedPreference使用了缓存策略,多进程模式下读写不可靠)
- Messenger(对AIDL封装了)
- AIDL(Binder代码自动生成工具)
- ContentProvider
- Socket
如何选择? 图片来源Android艺术开发探索
android的IPC通信选择.png
Binder(客户端/服务端架构 C/S架构)
Android为什么采用Binder:https://www.zhihu.com/question/39440766/answer/81511893
要进行进程通信就需要序列化。android也提供了自己的序列化方案Parcelable接口,我们实现读写方法就好了,读写都要按顺序。
Pracelable(内存序列化优先使用)和Serializable(本地序列化优先)
序列化本地存储或者通过网络传输建议使用Serializable
Intent间传递优先用Pracelable
先看下大致流程(图片来源huachao1001博客)
调用过程.pngBinder是一个虚拟的物理设备,他有自己的驱动,同时也是ServiceManager与其他Manager的连接者,比如ActivityManger和ServiceManager,也是客户端和服务端的媒介(其实说白了就是媒介),当bindService的时候会返回Binder对象,发起远程请求会挂起当前线程,直到服务器进程返回数据,所以UI线程不能发起耗时的远程请求。
大致流程:服务端进程的类继承Binder类,我们拥有Binder的引用,但是这个不是实际的客户端Binder对象,而是在Binder驱动做一次映射,设备驱动根据引用对象找到对应的远程进程,客户端调用远程函数的时候,把数据写到Pracel里面,调用transact时候会把参数,标识符等数据放到客户端的共享内存中,然后Binder驱动从客户端共享内存中读取数据,把他copy到对应服务端的共享内存中去,服务端执行完就把写入自己的共享内存中,此时客户端已经有了服务端相关对象引用,服务端直接唤醒客户端线程调用就行了。所以只进行了一次copy,效率高,而且安全。
Binder驱动(图片来源huachao1001博客).pngAIDL只是一种工具方便生成代码,可以自己手写Binder的和生成的代码一样,所以AIDL不是必需品
Binder有两个方法linkToDeath和unlinkToDeath
如果服务端进程异常退出,那么Binder这个媒介就没得玩了,也就消失了,买卖双方都没了,还怎么玩?
我们可以在服务中onServiceDisconnected中重连远程服务
还一种是给 Binder 设置一个死亡代理(DeathRecipient),就是告诉交易失败后你怎么做,都是重新连接
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
//移除以前的代理,执行unlinkToDeath将设置的死亡代理标志清除
//重新绑定服务
}
}
只是简单了解下,有机会再深入研究下。
网友评论