学习Android特有的Binder

最近突然写了很多文章,觉得自己对android系统和java知识也是进行了深层次学习,也趁着这段时间更加成长。以后也会继续学习,继续写博客。

IPC

IPC就是进程间通信,体现在以下几个方面

  1. Windows中的剪切板,管道,邮槽
  2. 管道(从百度百科我们了解到大概是这样的,Linux任何事物都视为文件,就是一个特殊文件,一个进程向这个文件写数据,而另一个进程则在文件中读取数据,其他问题我们不考虑)
  3. 共享内存(共享单车用过没?大概差不多,既然共享了更新会及时的)
  4. 信号量(也叫信号灯,同步用的,一个线程完成操作了就通过信号量告诉另外一个线程进行操作,信号量可以为红灯/黄灯/绿灯.....)和互斥量(我们平常用的锁,互斥用的,一个线程占用了资源,另外的线程就不能访问,只能为解锁/上锁)有区别
  5. 套接字(TCP/IP的封装)

android中的IPC通信

  1. Bundle(实现Parcelable接口)
  2. 文件共享(sharedPreference使用了缓存策略,多进程模式下读写不可靠)
  3. Messenger(对AIDL封装了)
  4. AIDL(Binder代码自动生成工具)
  5. ContentProvider
  6. Socket

如何选择? 图片来源Android艺术开发探索


学习Android特有的Binder_第1张图片
android的IPC通信选择.png

Binder(客户端/服务端架构 C/S架构)

Android为什么采用Binder:https://www.zhihu.com/question/39440766/answer/81511893

要进行进程通信就需要序列化。android也提供了自己的序列化方案Parcelable接口,我们实现读写方法就好了,读写都要按顺序。

Pracelable(内存序列化优先使用)和Serializable(本地序列化优先)

序列化本地存储或者通过网络传输建议使用Serializable
Intent间传递优先用Pracelable

先看下大致流程(图片来源huachao1001博客)

学习Android特有的Binder_第2张图片
调用过程.png

Binder是一个虚拟的物理设备,他有自己的驱动,同时也是ServiceManager与其他Manager的连接者,比如ActivityManger和ServiceManager,也是客户端和服务端的媒介(其实说白了就是媒介),当bindService的时候会返回Binder对象,发起远程请求会挂起当前线程,直到服务器进程返回数据,所以UI线程不能发起耗时的远程请求。

大致流程:服务端进程的类继承Binder类,我们拥有Binder的引用,但是这个不是实际的客户端Binder对象,而是在Binder驱动做一次映射,设备驱动根据引用对象找到对应的远程进程,客户端调用远程函数的时候,把数据写到Pracel里面,调用transact时候会把参数,标识符等数据放到客户端的共享内存中,然后Binder驱动从客户端共享内存中读取数据,把他copy到对应服务端的共享内存中去,服务端执行完就把写入自己的共享内存中,此时客户端已经有了服务端相关对象引用,服务端直接唤醒客户端线程调用就行了。所以只进行了一次copy,效率高,而且安全。

学习Android特有的Binder_第3张图片
Binder驱动(图片来源huachao1001博客).png

AIDL只是一种工具方便生成代码,可以自己手写Binder的和生成的代码一样,所以AIDL不是必需品

Binder有两个方法linkToDeath和unlinkToDeath

如果服务端进程异常退出,那么Binder这个媒介就没得玩了,也就消失了,买卖双方都没了,还怎么玩?
我们可以在服务中onServiceDisconnected中重连远程服务
还一种是给 Binder 设置一个死亡代理(DeathRecipient),就是告诉交易失败后你怎么做,都是重新连接

private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    @Override
    public void binderDied() {
        //移除以前的代理,执行unlinkToDeath将设置的死亡代理标志清除
        //重新绑定服务
    }
}

只是简单了解下,有机会再深入研究下。

你可能感兴趣的:(学习Android特有的Binder)