生活既是修行

1. android 中多进程模式

android 进程间通信的方式
1.Intent
2.文件共享
3.AIDL
4.Messenger
5.ContentProvider
6.RemoteViews
7.socket

1.1 多进程的开启方式

android中使用多进程只有一种方法,就是给四大组件在AndroidMenifest 中指定android:processs属性,那么问题来了,我们常常会使用两种指定方式:

android:process=":remote"
android:process="com.android.test"

这两种方式有何区别?

  • 1.":"的含义是要在进程名“remote”前加上包名的,加":"是一种简写
    1. ":"开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中。不以":"命名的进程属于全局进程,其他应用通过ShareUID 方式可以和它跑在同一个进程中

android 系统会为每个应用分配一个唯一的UID,相同UID的应该可以共享数据,如果两个应用通过相同ShareUID跑在同一个进程中,还需要有相同签名才可以相互访问私有数据,比如 data目录、组件信息等,跑在同一进程中,当然可以共享内存数据。
所有运行在不同进程中的四大组件,如果他们需要通过内存来共享数据,都会失败
一般来说,多进程会照成如下的一些问题:

1.静态成员和单例模式完全失效
2.线程同步机制失效
3.SharePreferences 的可靠性下降
4.Application 可能多次创建

2. IPC中一些基础概念

2.1Seriailzable 接口

Serializable 是Java 提供的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作,
SerialVersionUID 需指定,否则可能会导致反序列化失败

2.2 Parcelable 接口

Parcelable接口也是一个接口,只要实现这个接口,这个类对象就可以实现序列化并通过Intent、Binder传递

3.下面主要分析下使用AIDL文件进行进程间通信

  1. 举一个使用aidl 进行IPC通信的例子
    MainActivity 和PersonService 分属于两个进程,我们用aidl 进行双向通信
    完成 MainActivity创建person对象传到service 中进行保存,activity主动向service
    拿所有数据,service以集合的方式返回所有数据

我们定义的IPersonService.aidl (aidl 文件路径要和package定义的包名路劲下)

// IPersonService.aidl package com.prsioner.androidaidldemo;  // Declare any non-default types here with import statements import com.prsioner.androidaidldemo.Person; interface IPersonService {         void savePersonInfo(in Person person);         List getAllPerson(); }

Person.aidl

// Person.aidlpackage com.prsioner.androidaidldemo;// Declare any non-default types here with import statementsparcelable Person;

编译后自动生成的接口类IPersonService 在build/generated/source/aidl/....

activity 作为client 端通过bindService启动service进程,传入一个ServiceConnection 来接受服务端在
客户端的引用 iService

IPersonService iService;ServiceConnection serviceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.e(tag,"onServiceConnected");            iService = IPersonService.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            Log.e(tag,"onServiceDisconnected()");        }};

activity 发送数据和接受数据

iService.savePersonInfo(person);List personList = iService.getAllPerson();

service 服务端的部分代码:

public IBinder onBind(Intent intent) {        return iBinder;    }private final IPersonService.Stub iBinder = new IPersonService.Stub(){@Overridepublic void savePersonInfo(Person person) throws RemoteException {       if(person !=null){                personList.add(person);       }       }       @Override       public List getAllPerson() throws RemoteException {            return personList;       }};

我们来看aidl 完成通信的具体实现过程

package com.prsioner.androidaidldemo;public interface IPersonService extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.prsioner.androidaidldemo.IPersonService{private static final java.lang.String DESCRIPTOR = "com.prsioner.androidaidldemo.IPersonService";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.prsioner.androidaidldemo.IPersonService interface, * generating a proxy if needed. */public static com.prsioner.androidaidldemo.IPersonService asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.prsioner.androidaidldemo.IPersonService))) {return ((com.prsioner.androidaidldemo.IPersonService)iin);}return new com.prsioner.androidaidldemo.IPersonService.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor = DESCRIPTOR;switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}case TRANSACTION_savePersonInfo:{data.enforceInterface(descriptor);com.prsioner.androidaidldemo.Person _arg0;if ((0!=data.readInt())) {_arg0 = com.prsioner.androidaidldemo.Person.CREATOR.createFromParcel(data);}else {_arg0 = null;}this.savePersonInfo(_arg0);reply.writeNoException();return true;}case TRANSACTION_getAllPerson:{data.enforceInterface(descriptor);java.util.List _result = this.getAllPerson();reply.writeNoException();reply.writeTypedList(_result);return true;}default:{return super.onTransact(code, data, reply, flags);}}}private static class Proxy implements com.prsioner.androidaidldemo.IPersonService{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public void savePersonInfo(com.prsioner.androidaidldemo.Person person) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);if ((person!=null)) {_data.writeInt(1);person.writeToParcel(_data, 0);}else {_data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_savePersonInfo, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}@Override public java.util.List getAllPerson() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.util.List _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getAllPerson, _data, _reply, 0);_reply.readException();_result = _reply.createTypedArrayList(com.prsioner.androidaidldemo.Person.CREATOR);}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_savePersonInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_getAllPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public void savePersonInfo(com.prsioner.androidaidldemo.Person person) throws android.os.RemoteException;public java.util.List getAllPerson() throws android.os.RemoteException;}

IInterface接口: 所有用Binder传输数据的接口都必须继承这个接口

Stub: 继承自Binder 实现我们定义的aidl类接口IPersonService,其实就是作为服务端的一个binder对象
Stub 中有一个DESCRIPTOR,它是Binder的唯一标识,其中两个int常量是用来标识我们在接口中定义的方法的

asInterface()方法 用于将服务端的Binder对象转换为客户端所需要的接口对象,该过程区分进程,如果进程一样,
就返回服务端Stub对象本身,否则呢就返回封装后的Stub.Proxy对象(服务端在客户度的代理对象)

onTransact() 方法 是运行在服务端的Binder线程中的,当客户端发起远程请求后,在底层封装后会交由此方法来处理。
通过code来区分客户端请求的方法

Proxy代理对象类我们主要看一下我们定义的方法savePersonInfo()和getAllPerson()就可以了,这两个方法都是运行在客户端,
当客户端发起远程请求时,_data会写入参数,然后调用transact方法发起RPC(远程过程调用)请求,同时挂起当前线程,
然后服务端的onTransact方法就会被调起,直到RPC过程返回后,当前线程继续执行,并从_reply取出返回值(如果有的话),并返回结果

最后附上示例代码地址:https://github.com/prsioner/androidAIDLDemo

更多相关文章

  1. Android——启动过程详解
  2. Android(安卓)adb setuid提权漏洞的分析
  3. android 零散笔记不定期更新 v16
  4. 2011.07.12(2)——— android Messenger 跨进程通信
  5. android 开发学习笔记 (一)
  6. Android应用开发试题(收集)
  7. Android中Message机制的灵活应用
  8. Android(安卓)SystemProperties 系统属性分析
  9. Android(安卓)Bundle类

随机推荐

  1. Matplotlib如何绘制多个子图
  2. TypeScript 3.3发布!看看增加了什么新功能
  3. 高效的10个Pandas函数,你都用过吗?
  4. 利用query()与eval()优化pandas代码
  5. pandas参数设置小技巧
  6. 原来Python自带了数据库,用起来真方便!
  7. QGIS+Conda+jupyter玩转Python GIS
  8. jieba分词-Python中文分词领域的佼佼者
  9. 详解seaborn可视化中的kdeplot、rugplot
  10. JavaScript 风格指南 [每日前端夜话(0x1C