进程
- 线程和进程
线程是系统调度的最小单位;进程是资源分配的最小单位 - 多进程
在清单文件中给四大组件设置android:process属性,两种方式
a. :remote
b. cc.catface.xapp.remote
a方式为当前应用的私有进程,其他应用进程不能访问之,进程名参考cc.catface.xapp:remote
b方式为全局进程,其他应用进程可以访问之,进程名参考cc.catface.xapp.remote
系统会为每个应用分配唯一UID,以隔离内存数据访问 - 四大组件多进程存在的问题
android为每个应用分配一个独立的虚拟机,系统会在创建新进程的同时,分配独立的虚拟机,所以进程间无法通过共享同一片内存区域来共享数据
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
- SP可靠性下降[I/O并发读/写]
- Application会多次创建[运行不同进程需要分配不同的虚拟机]
序列化Serializable和Parcelable(*)
参考javascript:void(0)
Binder
安卓中常见IPC方式及使用场景
方式 | 优点 | 缺点 | 使用场景 |
Bundle | 数据类型限制 | 四大组件 | |
文件共享 | 并发 | 大量IO | |
AIDL | 安卓独有快速功能强大 | 为第三方app提供各种服务方法 | |
Messenger | aidl的封装传递Message对象消息 | 配合Handler和Message | 传递简单标识 |
ContentProvider | aidl的封装操作数据库 | 跨进程CRUD | |
Socket | 网络 |
简谈AIDL源码
- aidl案例
package cc.catface.aidls.login;
interface Test {
void hello(String name);
}
- 根据aidl生成的接口
package cc.catface.aidls.login;
public interface Test extends android.os.IInterface {
public static class Default implements cc.catface.aidls.login.Test {}
public static abstract class Stub extends android.os.Binder implements cc.catface.aidls.login.Test {}
public void hello(java.lang.String name) throws android.os.RemoteException;
}
2.1、Test接口,继承IInterface,IInterface包含唯一抽象方法IBinder asBinder()
,用于检索并返回与此接口关联的Binder对象;
2.2、Default类,Test接口的默认实现;
2.3、Stub[桩类],实现Test接口,其asBinder方法会根据,C/S在同一进程,返回当前Stub,即Binder对象;若C/S不在同一进程,返回远程Binder对象;
2.4、hello抽象方法,aidl中的方法声明;
2.5、IInterface接口[系统]
public interface IInterface {
public IBinder asBinder();
}
IInterface是Binder接口的基类;asBinder方法用于检索并返回与此接口关联的Binder对象;
- Default类
public static class Default implements cc.catface.aidls.login.Test {
@Override public void hello(java.lang.String name) throws android.os.RemoteException {}
@Override public android.os.IBinder asBinder() {
return null;
}
}
Default是Test接口的默认空实现类,内部方法也为空实现,asBinder方法返回null;
- Stub类
public static abstract class Stub extends android.os.Binder implements cc.catface.aidls.login.Test {
private static final java.lang.String DESCRIPTOR = "cc.catface.aidls.login.Test";
public Stub() {//...}
public static cc.catface.aidls.login.Test asInterface(android.os.IBinder obj) {//...}
@Override public android.os.IBinder asBinder() {//...}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {//...}
private static class Proxy implements cc.catface.aidls.login.Test {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {//...}
@Override public android.os.IBinder asBinder() {//...}
public java.lang.String getInterfaceDescriptor() {//...}
@Override public void hello(java.lang.String name) throws android.os.RemoteException {//...}
public static cc.catface.aidls.login.Test sDefaultImpl;
}
static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
public static boolean setDefaultImpl(cc.catface.aidls.login.Test impl) {//...}
public static cc.catface.aidls.login.Test getDefaultImpl() {//...}
}
4.1、桩类Stub,继承Binder,客户端通过Stub拿到Binder实例,来调用服务端方法;
4.2、DESCRIPTOR常量,描述服务的标识,即当前服务标识为cc.catface.aidls.login.Test
;参考getSystemService(Context.CAMERA_SERVICE);
和getSystemService(Context.ACTIVITY_SERVICE);
等;
4.3、Stub构造方法
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
4.3.1、attachInterface为Binder中的方法
public class Binder implements IBinder {
private IInterface mOwner;
private String mDescriptor;
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
//...
}
将接口与Binder关联,便于后续的asInterface方法获取对应的本地或远程Binder对象;
4.4、asInterface方法
public static cc.catface.aidls.login.Test asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof cc.catface.aidls.login.Test))) {
return ((cc.catface.aidls.login.Test) iin);
}
return new cc.catface.aidls.login.Test.Stub.Proxy(obj);
}
将Stub(IBinder)对象转换为Test接口,通过queryLocalInterface方法判断C/S是否在同一进程,若在同一进程,直接返回Stub.this即当前Stub;若不在同一进程,inn为空,并通过Proxy代理创建远程IBinder对象,即提供远程Test服务的Binder;
4.4.1、queryLocalInterface方法
public class Binder implements IBinder {
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
//...
}
检索descriptor描述的Binder对象的本地实现,如果返回null,则需要实例化一个代理类,以便通过transact方法对调用进行编组处理;通过实际调用得出结论,对于同样的Test.Stub.asInterface(service);
方法调用,C/S在不同进程,返回的iin为null,在同一进程,返回的iin为TestService$Binder@11064;
4.5、asBinder方法
@Override
public android.os.IBinder asBinder() {
return this;
}
返回当前Binder对象
4.6、onTransact方法
@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_hello: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
this.hello(_arg0);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
服务端调用,code为方法标识,参考4.8;data为客户端传参,其中的_arg0为hello方法的入参name;reply为hello方法处理后的返回值;return true标识该方法在服务端成功处理并响应;不在同一进程的客户端会通过Proxy中的mRemote对象,即远程Binder对象,调用transact方法,最终调用到当前服务端的onTransact方法;
4.7、Proxy代理,当C/S不在同一进程,就要用Proxy来实例化远程Binder对象,并执行transact方法;详见5.
4.8、TRANSACTION_hello标识,aidl中声明的方法标识
4.9、setDefaultImpl方法和getDefaultImpl方法
public static boolean setDefaultImpl(cc.catface.aidls.login.Test impl) {
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static cc.catface.aidls.login.Test getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
public static cc.catface.aidls.login.Test sDefaultImpl;
声明在Proxy内部,参考5.,用来操作默认的Test对象,并在Proxy进行服务方法处理时使用,如Proxy=>hello(){getDefaultImpl().hello(name)};
- Proxy代理类
private static class Proxy implements cc.catface.aidls.login.Test {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {//...}
@Override public android.os.IBinder asBinder() {//...}
public java.lang.String getInterfaceDescriptor() {//...}
@Override public void hello(java.lang.String name) throws android.os.RemoteException {//...}
public static cc.catface.aidls.login.Test sDefaultImpl;
}
5.1、Proxy
private static class Proxy implements cc.catface.aidls.login.Test {
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 hello(java.lang.String name) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
boolean _status = mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().hello(name);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
public static cc.catface.aidls.login.Test sDefaultImpl;
}
5.2、mRemote
调用远程服务的Binder对象
5.5、hello方法
客户端调用hello方法,_data
为客户端入参,mRemote.transact调用远程服务端的onTransact方法,_status
为服务端处理成功失败标志,参考4.6,若是成功,_reply
为方法返回值;
5.6、boolean _status = mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
_status
为服务端的onTransact方法处理返回值,但一般好像都是true;onTransact方法的源码注释为,成功调用时返回true;返回false通常用于表示您没有理解事务代码;
aidl调用补充
当C/S不在同一进程,C调用hello方法的流程为,先调用本地Test里Proxy的hello方法,通过boolean _status = mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
调用远程服务端的Test里Stub的public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
方法,若该方法返回false;
这里常见的都是返回true,如何返回false呢,可以删除服务端的aidl文件,直接将Test复制进src相应目录下,手动改成返回false;
此时_status
即为false,再判断getDefaultImpl()是否为空,sDefaultImpl可以在客户端连接服务后调用Test.Stub.setDefaultImpl(new Test() {})
设置一个由客户端实现的本地默认处理类;