Android进阶笔记:AIDL内部实现详解 (二)
接著上一篇分析的aidl的流程解析。知道了aidl主要就是利用Ibinder來實現跨進程通信的。既然是通過對Binder各種方法的封裝,那也可以不使用aidl自己通過Binder來實現跨進程通訊。那么這篇博客就主要就寫一下通過上篇(Android進階筆記:AIDL詳解(一))總結的知識來自己實現跨進程通訊從而更加透徹的了解aidl的核心邏輯。
首先上一篇博客(Android進階筆記:AIDL詳解(一))中總結出一個結論————“onTransact方法是提供給server端用的,transact方法(內部類proxy封裝了transact方法)和asInterface方法是給client端用的。”因此很清楚,只要我們在Server端實現跨進程需要調用的方法(類似aidl的接口實現)和onTransact方法,而服務端只要通過獲得的IBinder對象來調用transact方法就可以代替aidl來實現跨進程通訊了。既然思路已經整理清楚了,那就一步一步來實現它。
Server端
首先Server端是要通過Service的onBind方法來給Client端一個Binder對象,那就先從這個Binder對象入手。那就先來創建了一個MyBinder類,代碼如下:
MyBinder.java
public class MyBinder extends Binder { //標記方法的 private static final int METHOD_ADD_CODE = 1001; //標識binder對象的 private static final String DESCRIPTION = "not use aidl"; @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { if (code == METHOD_ADD_CODE) { //驗證一下binder data.enforceInterface(DESCRIPTION); //從parcel對象中讀取參數 int arg0 = data.readInt(); int arg1 = data.readInt(); //寫入結果 reply.writeInt(add(arg0, arg1)); return true; } return super.onTransact(code, data, reply, flags); } private int add(int arg0, int arg1) { return arg0 + arg1; } }代碼非常簡單,只是重新寫了一下onTransact方法。其實一共只有4步:
接著只要把這個自己定義的MyBinder類的實例通過Service.onBInder方法返回給Client端就可以了。
MyService.java
public class MyService extends Service { private MyBinder myBinder; public MyService() { } @Override public void onCreate() { super.onCreate(); //創建實例 myBinder = new MyBinder(); } @Override public IBinder onBind(Intent intent) { //返回自定義的binder對象 return myBinder; } }Client端
client端的代碼無非就是把之前寫在aidl中的proxy內部類的方法拿出來了。具體看代碼:
WithoutAidlActivity.java
public class WithoutAidlActivity extends AppCompatActivity { private ServiceConnection serviceConnection; private IBinder binder; //以下兩個參數要和server端保持一致 //標記方法的(告知server端調用哪個方法) private static final int METHOD_ADD_CODE = 1001; //標識binder對象的 private static final String DESCRIPTION = "not use aidl"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_without_aidl); serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("onServiceConnected", "onServiceConnected: connected success!"); binder = service; //這里就代替aidl中的proxy來直接調用transact方法 //先準備參數 Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(DESCRIPTION); data.writeInt(123); data.writeInt(456); try { //調用transact方法 binder.transact(METHOD_ADD_CODE, data, reply, 0); //獲得結果 int result = reply.readInt(); Log.d("onServiceConnected", "result = " + result); } catch (RemoteException e) { e.printStackTrace(); } finally { data.recycle(); reply.recycle(); } } @Override public void onServiceDisconnected(ComponentName name) { binder = null; } }; bindService(new Intent("com.coder_f.aidlserver.MyService"), serviceConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(serviceConnection); } }首先連接成功后在serviceConnection.onServiceConnected方法中獲得了IBinder實例,然后總共做了3個事情:
完成以上工作就可以不通過aidl實現跨進程通訊了。但是還是要說一下,這里我們server端調用的只是一個簡單的add方法不耗時的,而transact方法則是在onServiceConnected方法中被調用的其實是在主線程中執行的。如果add方法換成一個耗時方法,那么主線程(UI線程)是會卡死的,調用transact方法時當前線程會被掛起知道結果被返回(有興趣可以去試試,只要在add方法里面加一個Thread.sleep就可以了)。所以最好的辦法就是起一個線程來調用transact方法。
? ? 本文轉自 一點點征服 ? 博客園博客,原文鏈接:http://www.cnblogs.com/ldq2016/p/8418909.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的Android进阶笔记:AIDL内部实现详解 (二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新书预告:《Linux 多线程服务端编程
- 下一篇: django ForeignKey的使用