有关AIDL的使用我就不多说了,今天主要讲的是AIDL的方法作用
AIDL是定义接口的一种语言,多使用跨进程通信的场景,比方说你现在需要获取到服务端的数据(这个服务端不是指提供接口的后台,而是与你当前应用不在一个进程的程序),这个时候你就需要跨进程去获取数据了.
OK,我们先看一下系统生成的AIDL接口:
public interface GetTokenService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
* 内部类的实现
* 实际上这个stub类就是一个binder类,我会对每个方法都一个解释,然后再做一下总结
*/
public static abstract class Stub extends android.os.Binder implements com.sumaott.auth.service.GetTokenService {
private static final java.lang.String DESCRIPTOR = "当前类的路径,会自动生成"; //标识方法
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.sumaott.auth.service.GetTokenService interface,
* generating a proxy if needed.
* 将服务端的binder对象转换成客户端所需要的AIDL对象,如果在同进程中,返回stub本身,否则返回stub.proxy
* 我们可以看代码
*/
public static com.sumaott.auth.service.GetTokenService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.sumaott.auth.service.GetTokenService))) { //这里是区分是否在一个进程中
**return ((com.sumaott.auth.service.GetTokenService) iin);** // 返回stub本身
}
**return new com.sumaott.auth.service.GetTokenService.Stub.Proxy(obj);** 否则返回stub.proxy
}
@Override
public android.os.IBinder asBinder() { //返回当前的Binder对象
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
//通过code确定客户端请求的目标方法是什么,
switch (code) {
case INTERFACE_TRANSACTION: { //接口错误,没找到对应的目标方法
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getToken: { //如果找到了对应的目标方法,执行方法,再向reply中写入返回值_result
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getToken();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//这个方法是运行在客户端的
private static class Proxy implements com.sumaott.auth.service.GetTokenService {
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;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public java.lang.String getToken() throws android.os.RemoteException {
//创建输入型对象_data,输出型对象_reply,返回值对象_result
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
//调用transact方法来发起RPC请求,同时将当期线程挂起,等待服务端的onTransact方法被调用直到RPC过程返 回,当期线程继续执行
mRemote.transact(Stub.TRANSACTION_getToken, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result; //在将获取到的值返回
}
}
static final int TRANSACTION_getToken = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public java.lang.String getToken() throws android.os.RemoteException;
}
注: GetTokenService 是类名,这个你可以自己去定义,getToken()方法是获取对应数据的一个类,你在获取数据时,需改成与服务端对应的数据结构和方法名
整个运行的逻辑: 首先使用整型ID去标识方法,如果有两个方法则再加一个整型ID,,接着声明了一个内部类stub类,然后通过asInterface方法去判断当前在是否在同一进程中,如果在,返回Stub对象,否则返回Stub.proxy对象, ,,在返回Stub.proxy对象之前会去执行Stub的Proxy内部代理类,然后在Proxy类里去调用transact方法来启动RPC(远程调用服务),同时会将当前线程挂起,然后onTransact方法会被执行,并将获取到的数据写入reply中,然后等到RPC过程结束后,回到当前线程也就是Proxy类里的getToken() 方法,然后获取到RPC之前写入在reply中的数据,最终我们就可以拿到对应的数据了
备注:RPC是耗时服务,不要在UI线程里去做这步操作