概念:
在Android中,每個程序都有自己的進程,當需要在不同的進程間傳遞對象時,該如何實現呢?
Java中不支持跨進程內存共享,因此要傳遞對象,需要把對象解析成操作系統能夠理解的數據模式,以達到跨界對象訪問的目的。這就是遠程程序調用RPC.
RPC (Remote Procedure Call)遠程程序調用
在Android中RPC的解決方案是通過AIDL方式來實現
Activity、Broadcast、ContentProvider、Service都可以實現跨進程的訪問
IPC (Inter-Progress Communication)內部進程通信
什麼是AIDL?
(Android Interface Definition Language)它是一種Android內部進程通信接口的描述語言,通過它定義進程間的通信接口,實現進程間通信。
AIDL實現RPC步驟:
1、在服務器端新增ICounter.aidl後綴的文件,裏面的內容爲接口的定義,注意:接口定義和方法定義都不能顯式指定修飾符。
2、該aidl文件會被自動編譯生成一個ICounter.java文件,其中包含一個靜態內部類Stub(Stub類繼承Binder類)和方法asInterface(方法的返回值爲ICounter實例,方法的參數爲IBinder)
3、在服務器端新增Service,該service的onBind()方法的返回值爲new ICounter.Stub(){public int getNum()},在該匿名內部類中實現getNum()方法
4、需要註冊該服務,並指定action(sign)
5、在客戶端要新增一個與服務器端完全一致的aidl文件,系統會自動生成與服務器端一樣的ICounter.java文件。
6、在Acitivity中以綁定的方式啓動服務,其中第一個參數Intent的action爲之前服務註冊的action(sign),ServiceConnection()實現類的onServiceConnected()方法中通過ICounter.Stub.asInterface(IBinder)來獲得ICounter實例
7、通過ICounter的實例調用getNum()方法,就可以在Activity中得到ICounter的getNum()方法的返回值。
案例三:
activity與service之間通過Binder對象的onTransact方法進行數據傳遞。
備註:當客戶端執行了transact方法時,就會回調對應的遠程Binder對象的onTransact方法。其中code是用來區分當前客戶端所調用的方法,data是輸入參數,這個參數不能爲NULL,即使你不需要傳遞任何參數你也應該傳遞一個空的Parcel對象。reply是含有遠程客戶端執行接口的Parcel對象,flags是附加的執行遠程操作的標誌,0表示正常的遠程調用,1表示不需要返回值的one-way調用。
MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyService.class);
bindService(intent,new MyConn(),BIND_AUTO_CREATE);
}
class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MyService.MyBinder binder = (MyService.MyBinder) iBinder;
// 獲得一個新的Parcel,相當於new一個對象
Parcel data = Parcel.obtain();
data.writeString("我是你的客戶端");
Parcel reply = Parcel.obtain();
try {
binder.transact(Binder.FIRST_CALL_TRANSACTION,data,reply,0);
String replyString = reply.readString();
Log.d("test1","從服務端來的數據====reply======"+replyString);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
}
Service:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
class MyBinder extends Binder{
/**
*Parcel 容器,用來存放數據,用Binder對象進行數據的傳遞
* data 從activity中過來的數據
* reply service到activity的回覆
*/
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
String dataString = data.readString();
Log.d("test2","從客戶端來的數據------data--------"+dataString);
reply.writeString("我是你的服務端");
return super.onTransact(code, data, reply, flags);
}
}
}