Android开发艺术探索 章2

作者: defalt的简书 | 来源:发表于2021-02-02 23:05 被阅读0次

    Android 的 IPC机制

    底层 使用Binder 或 Socket

    使用多进程

    在Android中只有一种方法: 给四大组件android:process属性.
    进程名为":"开头, 为当前app的私有进程, 其他app不能和它跑在同一个进程里.
    进程名不为":"开头的, 为全局进程, 其他应用可以通过ShareUID方式和它跑在同一个进程里.
    (非常规: 在native层用JNI来Fork一个进程)

    应用的UID:

    Android会为每一个app分配不同的UID, 具有相同UID的两个应用才能共享数据, 但是必须签名也一致. 这样他们能互相访问对方的私有数据, 如果跑在同一个进程中, 除了共享数据, 还能共享内存数据.

    多进程运行机制:

    Example: 静态变量是相互独立的, 在一个进程中更改了值, 另一个进程的副本不会更改. Android会为每一个进程分配独立的虚拟机, 不同的虚拟机在内存分配上有不同的空间地址.

    结论: 通过内存来共享数据, 都是失败的.

    使用android:process会带来的问题:

    1. 静态成员和单例模式完全失效;
    2. 线程同步机制完全失效;
    3. SharedPreferences可靠性下降 (不支持两个进程同时执行写操作)
    4. Application会多次创建

    IPC基础概念

    Binder

    Binder的工作机制:

    Android中的IPC方式

    Bundle/ 文件共享(不建议使用系统的SharedPreferences) /Messenger(轻量级IPC,底层依然是AIDL)工作原理(Page70 & 代码)/AIDL

    AIDL支持的数据类型:基本数据类型;String和CharSequence;List只支持ArrayList,里面每个元素都必须被AIDL支持;Map只支持HashMap,里面每个元素都必须被AIDL支持(包括key和value);Parcelable;AIDL接口本身;

    服务端可以使用CopyOnWriteArrayList和ConcurrentHashMap来进行自动线程同步,客户端拿到的依然是ArrayList和HashMap;

    服务端和客户端之间做监听器,服务端需要使用RemoteCallbackList,否则客户端的监听器无法收到通知(因为服务端实质还是一份新的序列化后的监听器实例,并不是客户端那份);

    客户端调用远程服务方法时,因为远程方法运行在服务端的binder线程池中,同时客户端线程会被挂起,所以如果该方法过于耗时,而客户端又是UI线程,会导致ANR,所以当确认该远程方法是耗时操作时,应避免客户端在UI线程中调用该方法。同理,当服务器调用客户端的listener方法时,该方法也运行在客户端的binder线程池中,所以如果该方法也是耗时操作,请确认运行在服务端的非UI线程中。另外,因为客户端的回调listener运行在binder线程池中,所以更新UI需要用到handler。

    客户端通过IBinder.DeathRecipient来监听Binder死亡,也可以在onServiceDisconnected中监听并重连服务端。区别在于前者是在binder线程池中,访问UI需要用Handler,后者则是UI线程。

    可通过自定义权限在onBind或者onTransact中进行权限验证。

    ContentProvider(有的手机上会出现不加uses-permission依然可以访问BookProvider的问题) f. Socket 一般用于网络通信,AIDL用这种方式会过于繁琐,不建议使用。

    Binder连接池,通过BinderPool的方式将Binder的控制与Service本身解耦,同时只需要维护一份Service即可。这里用到了CountDownLatch,大概解释下用意:线程在await后等待,直到CountDownLatch的计数为0,BinderPool里使用它的目的是为了保证Activity获取BinderPool的时候Service已确定bind完成

    相关文章

      网友评论

        本文标题:Android开发艺术探索 章2

        本文链接:https://www.haomeiwen.com/subject/gcbutltx.html