进程
-
线程和进程
线程是系统调度的最小单位;进程是资源分配的最小单位
-
多进程
在清单文件中给四大组件设置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(*)
参考https://blog.youkuaiyun.com/itCatface/article/details/85948341
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() {})设置一个由客户端实现的本地默认处理类;
1630

被折叠的 条评论
为什么被折叠?



