1 回答

TA貢獻12條經(jīng)驗 獲得超7個贊
我們就看看IMyInterface.Stub吧:
public static abstract class Stub extends android.os.Binder implements aidl.IMyInterface {
..........
}
可以看到,Stub是IMyInterface中的一個靜態(tài)抽象類,繼承了Binder,并且實現(xiàn)了IMyInterface接口。這也就解釋了我們定義IMyInterface.Stub的時候為什么需要實現(xiàn)IMyInterface中的方法了,也說明了為什么我們可以把IMyInterface.Stub向上轉型成IBinder了。
Activity中的IMyInterface?
在Activity中,通過ServiceConnection連接MyService并成功回調(diào)onServiceConnected中我們把傳回來的IBinder通過IMyInterface.Stub.asInterface(service)轉換成為IMyInterface,那就來看看這里是如何轉換的吧:
public static abstract class Stub extends android.os.Binder implements aidl.IMyInterface {
..........
public static aidl.IMyInterface asInterface(android.os.IBinder obj) {
? ?if ((obj == null)) {
? ? ? ?return null;
? ?}
? ?
? ?android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
? ?if (((iin != null) && (iin instanceof aidl.IMyInterface))) {
? ? ? ?return ((aidl.IMyInterface) iin);
? ?}
? ?return new aidl.IMyInterface.Stub.Proxy(obj);
}
}
首先,我們因該明白的是,傳回來的IBinder就是我們在Service的onBind( )方法所return的IBinder,然后我們調(diào)用Stub中的靜態(tài)方法asInterface并把返回來的IBinder當參數(shù)傳進去。?
在asInterface方法中,首先判斷了傳進來的IBinder是不是null,如果為null就返回一個null;接著就判斷傳進來的IBinder是不是就在當前進程里面,如果是的話就直接返回IMyInterface,不是的話就返回IMyInterface.Stub.Proxy(obj)。這里我覺得需要明白的是:直接返回的IMyInterface是實現(xiàn)了定義的接口方法getInfor的。因為在IMyInterface.Stub中所實現(xiàn)的。當然如果是在同一進程中,那么我們調(diào)用IMyInterface的方法時就是在本地調(diào)用方法,直接調(diào)用就可以了。
如果沒在同一進程,就會返回IMyInterface.Stub.Proxy(obj):
private static class Proxy implements aidl.IMyInterface {
? ? ? ?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 java.lang.String getInfor(java.lang.String s) throws android.os.RemoteException {
? ? ? ? ? ?android.os.Parcel _data = android.os.Parcel.obtain();
? ? ? ? ? ?android.os.Parcel _reply = android.os.Parcel.obtain();
? ? ? ? ? ?java.lang.String _result;
? ? ? ? ? ?try {
? ? ? ? ? ? ? ?_data.writeInterfaceToken(DESCRIPTOR);
? ? ? ? ? ? ? ?_data.writeString(s);
? ? ? ? ? ? ? //傳送數(shù)據(jù)到遠程的
? ? ? ? ? ? ? ?mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
? ? ? ? ? ? ? ?_reply.readException();
? ? ? ? ? ? ?//接受從遠端傳回的數(shù)據(jù)
? ? ? ? ? ? ? ?_result = _reply.readString();
? ? ? ? ? ?} finally {
? ? ? ? ? ? ? ?_reply.recycle();
? ? ? ? ? ? ? ?_data.recycle();
? ? ? ? ? ?}
? ? ? ? ? ?return _result;
? ? ? ?}
? }
? ?static final int TRANSACTION_getInfor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
在Proxy中,我們首先把Service連接成功返回的IBinder它的內(nèi)部變量mRemote,這里在提一下,這里得IBinder還是是MyService中onBind所返回的。然后,當我們調(diào)用IMyInterface的方法的時候,其實就是調(diào)用的Proxy的方法了,這也是為什么這個類叫做Porxy的原因了。
當調(diào)用IMyInterface.getInfor(String s) ,我們就看Proxy中的getInfor,先獲取了兩個Parcel對象 _data、_data,從變量名就可以看出,一個是傳送數(shù)據(jù)的,另一個則是接受返回數(shù)據(jù)的。接著,向_data中寫入了DESCRIPTOR(也就是這個類的全名),再寫入了方法參數(shù)。然后就到了最重要的一步了,
mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);?
這里我們調(diào)用了IBinder的transact方法,來把數(shù)據(jù)傳給遠端的服務器。然后在我們遠程的MyService中,里面的Stub中就會回調(diào)onTransact()(因為你把數(shù)據(jù)傳個遠程的服務,遠端的服務收到數(shù)據(jù)也就回調(diào)了)
注意:這里是在遠程的服務里調(diào)用的。
@Overridepublic
boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
? ?switch (code) {
? ? ? ?case INTERFACE_TRANSACTION: {
? ? ? ? ? ?reply.writeString(DESCRIPTOR);
? ? ? ? ? ?return true;
? ? ? ?}
? ? ? ?case TRANSACTION_getInfor: {
? ? ? ? ? ?data.enforceInterface(DESCRIPTOR);
? ? ? ? ? ?java.lang.String _arg0;
? ? ? ? ? //取出參數(shù)
? ? ? ? ? ?_arg0 = data.readString();
? ? ? ? ? // 遠程服務調(diào)用自己本地實現(xiàn)的方法獲取返回值
? ? ? ? ? ?java.lang.String _result = this.getInfor(_arg0);
? ? ? ? ? ?reply.writeNoException();
? ? ? ? ? //寫入返回值
? ? ? ? ? ?reply.writeString(_result);
? ? ? ? ? ?return true;
? ? ? ?}
? ?}
? ?return super.onTransact(code, data, reply, flags);
}
onTransact方法是在Stub的內(nèi)部實現(xiàn)的。
先看一下它的四個參數(shù):?
code:每個方法都有一個int類型的數(shù)字用來區(qū)分(后面中的swicth),在我們例子中也就是我們Proxy中的Stub.TRANSACTION_getInfor。?
data:傳過來的數(shù)據(jù),其中包含我們的參數(shù),以及類的描述。?
reply:傳回的數(shù)據(jù),我們要寫入是否發(fā)生了Exception,以及返回值?
flags:該方法是否有返回值 ,0表示有返回值。
調(diào)用onTransact就表示有數(shù)據(jù)傳來,首先就會通過swicth判斷是哪個方法,然后取出方法參數(shù),調(diào)用本地實現(xiàn)的方法獲取返回值,寫入返回值到reply。最后,返回true,才會把數(shù)據(jù)發(fā)送出去,發(fā)揮false就不會把結果返回給Activity了。這里也就是說,只有返回true,我們Proxy中才能接受從遠端傳回的數(shù)據(jù)。
? ? ? //傳送數(shù)據(jù)到遠程的
? ? ? ?mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0)
? ? ? ?_reply.readException()
? ? ? //接受從遠端傳回的數(shù)據(jù)
? ? ? ?_result = _reply.readString()
注意:Service也是把數(shù)據(jù)發(fā)送出來,讓客戶端接受的。
Service發(fā)出了數(shù)據(jù),客戶端接收到了,就會一層一層返回去。所以,當我們簡單的調(diào)用IMyInterface的getInfor時候,先是Proxy的transact發(fā)送出數(shù)據(jù),然后服務端的onTransact接受并處理傳來的數(shù)據(jù),再把處理得到的數(shù)據(jù)寫入返回值并發(fā)送給客戶端,客戶端讀取值后就成為調(diào)用方法的返回值返回了。
- 1 回答
- 0 關注
- 913 瀏覽
添加回答
舉報