第二章 IPC机制(新)

一、进程和线程、Android进程间最具特色的通信方式
进程和线程都是cpu执行的时间片段,只是颗粒度大小不同。进程需要切换上下文,线程不用。
不同的任务可以比作进程;可是完成一个任务需要从不同的方面同时进行,这就是线程。
Android基于Linux内核,可是它的进程间通信并不能完全继承自Linux。相反,它有自己的进程间通信方式。最有特色的就是Binder。

二、Android为什么要有多进程?
1、一个应用因为某些原因自身需要采用多进程模式实现。原因有很多,可能是某些模块由于特殊原因需要运行在单独的进程中;又可能是为了加大一个应用可使用的内存。
2、当前应用需要向其他应用获取数据。

三、怎么开启多进程?
给四大组件在AndroidMenifest中指定android:process属性。

四、多进程的UID
Android系统会为每个应用分配一个唯一的UID。也就是说,我在一个应用里开多进程,虽然开启了不同的进程,但是它们的UID是相同的。
UID相同的进程可以共享目录文件数据(它们的data目录就是同一个),(如果对方的组件声明权限)还可以不需要权限启动对方的组件(同时还需要签名相同,在一个应用里开的多进程,签名肯定相同)

五、多进程会造成的几个问题
1、静态成员和单例模式完全失效
2、线程同步机制完全失效
3、SharedPreferences的可靠性下降
SharedPreferences也属于文件的一种,但是由于系统对它的读/写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多线程模式下,系统对它的读/写就变得不可靠,当面对高并发的读/写访问,SharedPreferences有很大几率会丢失数据,因此,不建议在进程间通信中使用SharedPreferences
4、Application会多次创建
可以这么理解,运行在同一个进程中的组件是属于同一个虚拟机和同一个Application的

六、进程间对象数据的传输
Serializable和Parcelable:Parcelable主要用在内存序列化上;Serializable用在将对象序列化到存储设备中或者将对象序列化后通过网络传输。

七、Binder(非常重要)
1、Binder外部的aidl接口类
这里写图片描述
这里写图片描述
这里写图片描述

2、我们在代码中实际用到的Binder类(Stub)(还有它的内部代理类Proxy)

Stub:

这里写图片描述

Stub内部的字段和方法:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

Proxy:

这里写图片描述

Proxy内部的字段和方法

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

3、给Binder设置死亡代理
Binder运行在服务端进程,如果服务端进程由于某种原因异常终止,这个时候我们到服务端的Binder连接断裂(称之为Binder死亡),会导致我们的远程调用失败。
我们可以通过linkToDeath给Binder设置一个死亡代理,当Binder死亡时,系统就会回调其binderDied方法,此时我们就可以通过unLinkToDeath方法解除之前Binder绑定的死亡代理,并重新绑定远程服务。

        //初始化死亡代理
        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
            @Override
            public void binderDied() {
                if(mBookManager == null){
                    return;
                }
                mBookManager.asBinder().unlinkToDeath(mDeathRecipient,0);
                mBookManager == null;
                //TODO:这里重新绑定Service
            }
        };
        //客户端绑定远程服务成功后,给Binder设置死亡代理
        mService = IBookManager.Stub.asInterface(binder);
        binder.linkToDeath(mDeathRecipient,0);

八、Android中的IPC方式

1、Bundle
由于Bundle实现了Parcelable接口,所以它可以方便的通过Intent发送从而在不同进程间传输。当然,我们在Bundle中附加的数据也要能够被序列化。

2、使用文件共享
如果并发读写,那么我们读出来的内容就有可能不是最新的,并发写更严重。所以这种方式适合对数据同步要求不高的进程间通信,并且要妥善处理好并发读写的问题

3、使用Messenger
底层实现是Binder。由于在服务端我们一次处理一个请求,所以在服务端我们不用考虑线程同步的问题。

4、使用AIDL
使用方式见http://blog.csdn.net/wwww_dong/article/details/78721590
1)在服务端需要处理数据同步问题,所以我们可以使用类似CopyOnWriteArrayList来自动的进行线程同步。
2)可以向服务端传递客户端的aidl监听器接口,在服务端注册成为观察者,从而达到观察者模式的效果。
客户端将监听器往服务端传时,在服务端操作的对象已经不再是Binder类了,而是它的内部类Proxy,所以不用再转化了,直接使用就可以。
3)RemoteCallbackList
背景:
可是因为注册和解注册时传到服务端的Binder是两个对象(对象在跨进程传输本质上都是反序列化的过程:,所以并不能通过简单的方式就达到解注册的功能。而是要使用RemoteCallbackList。
定义:
RemoteCallbackList是系统提供的专门用于删除跨进程listener的接口。RemoteCallbackList是一个泛型,支持管理任意的AIDL接口。

 public class RemoteCallbackList<E extends IInterface>

功能:
客户端申请解注册时,从自己的集合中删除对应的listener;
当客户端进程终止后,它能够自动移出客户端注册的listener;
其内部自动实现了线程同步功能;
使用方法:

//定义观察者数据集合
private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new 
                RemoteCallbackList<IOnNewBookArrivedListener>();
//注册成为观察者
mListener.register(listener);
//解注册观察者
mListener.unRegister(listener);
//当有新消息时,如果遍历观察者集合,并一个个的通知它们
final int N = mListenerList.beginBroadcast();//1
for(int i = 0; i<N; i++){
    IOnNewBookArrivedListener l = mListenerList.getBroadcastItem(i);//2
    if(i != null){
        try{
            l.onBookArrived(book);
        }catch(RemoteException e){
            e.printStackTrace();
        }
    }
}
mListenerList.finishBroadcast();//3

4)onServiceConnected、onServiceDisconnected都运行在UI线程
5)Binder死亡时,可以通过死亡代理重新连接,也可以通过onServiceDisconnected方法重连。两者的不同是,前者运行在客户端的binder线程池中,后者运行在UI线程中
6)绑定时,服务端可以在两个地方进行权限验证。一个是在onBind中,一个是在onTransact中

5、使用ContentProvider
底层实现是Binder。
六个抽象方法:onCreate、getType、insert、delete、update、query。onCreate运行在主线程,增删改查运行在服务端的Binder线程池,getType返回请求对应的MIME类型,没有的话返回null或者“/”。
ContentProvider主要以表格形式来组织数据,也可以文件、内存的形式。
支持自定义调用,通过ContentResolver的Call方法和ContentProvider的Call方法。
SQLiteDataBase内部对数据库的操作有同步处理,但SQLiteDataBase对象之间无法进行线程同步。

6、使用Socket

九、线程池BinderPool
在BinderPool里bindService,从而建立binder连接,只不过这个binder连接的作用是从服务端拿取其他binder,这样BinderPool这个类就拥有了从特定的远程Service里拿取各种binder的能力。所以,只要我们拥有BinderPool,我们就可以拿到远程Service的各种模块的Binder,从而进行各种RPC。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值