個人博客地址 http://dandanlove.com/
在學習Binder和AIDL的過程中遇到的一些有意思的事情~!
linkToDeath機制,我們先看看官網(wǎng)如何介紹:
When working with remote objects, you often want to find out when they are no longer valid. There are three ways this can be determined:
The [transact()](https://developer.android.com/reference/android/os/IBinder.html#transact(int, android.os.Parcel, android.os.Parcel, int))
method will throw a RemoteException
exception if you try to call it on an IBinder whose process no longer exists.
The pingBinder()
method can be called, and will return false if the remote process no longer exists.
The [linkToDeath()](https://developer.android.com/reference/android/os/IBinder.html#linkToDeath(android.os.IBinder.DeathRecipient, int))
method can be used to register a IBinder.DeathRecipient
with the IBinder, which will be called when its containing process goes away.
總結:我們可以通過三種方式來檢測遠程對象是否存活刹衫。
- 調用遠程方法的時候捕獲RemoteException(DeadObjectException);
- 調用IBinder的pingBinder()進行檢測特铝;
- 實現(xiàn)IBinder.DeathRecipient接口回調祭衩;
Binder意外中斷
往往是由于服務端進程意外停止了,這時我們需要重新連接服務钦讳。
那么我們可以使用linkToDeath機制矿瘦,如果使用bindService那么還可以通過ServiceConnection.onServiceDisconnected方法進行重連。
捕獲RemoteException
在調用遠程服務的時候愿卒,如果服務掛掉匪凡,那么我們客戶端會接受到拋出的RemoteException異常,監(jiān)聽該異常進行處理掘猿。
android.os.DeadObjectException
at android.os.BinderProxy.transact(Native Method)
at com.tzx.aidlinout.aidl.IBookManager$Stub$Proxy.addInBook(IBookManager.java:159)
at com.tzx.aidlinout.MainActivity.onClick(MainActivity.java:117)
at android.view.View.performClick(View.java:3514)
at android.view.View$PerformClick.run(View.java:14125)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4439)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
pingBinder進行檢測
pingBinder()方法會返回當前遠程服務的狀態(tài)(true|false)
IBinder.DeathRecipient
實現(xiàn)了IBinder.DeathRecipient接口的參數(shù)調用linkToDeath()方法病游,可以在binderDied方法中處理中斷邏輯。
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.d("binder", "binderDied calling~!");
}
}, 0);
總結
先看下邊的log稠通,從中我們可以總結出以上4中Binder中斷處理方法的執(zhí)行順序:
linkToDeath > onServiceDisconnected > pingBinder > transact()
//調用遠程服務
binder.pingBinder = true
Binder Thread #2 //遠程服務的當前線程名稱
//kill遠程服務存在的進程
binderDied calling~!
onServiceDisconnected
binder.pingBinder = false
android.os.DeadObjectException
at android.os.BinderProxy.transact(Native Method)
at com.tzx.aidlinout.aidl.IBookManager$Stub$Proxy.addInBook(IBookManager.java:159)
at com.tzx.aidlinout.MainActivity.onClick(MainActivity.java:117)
at android.view.View.performClick(View.java:3514)
at android.view.View$PerformClick.run(View.java:14125)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4439)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
擴展
這里講一個Android源碼中的類:RemoteCallbackList衬衬。
它在內部對列表中的每一個數(shù)據(jù)實現(xiàn)了Callback。而Callback實現(xiàn)了IBinder.DeathRecipient接口改橘。
public class RemoteCallbackList<E extends IInterface> {
ArrayMap<IBinder, Callback> mCallbacks
= new ArrayMap<IBinder, Callback>();
private Object[] mActiveBroadcast;
private int mBroadcastCount = -1;
private boolean mKilled = false;
private final class Callback implements IBinder.DeathRecipient {
final E mCallback;
final Object mCookie;
Callback(E callback, Object cookie) {
mCallback = callback;
mCookie = cookie;
}
public void binderDied() {
synchronized (mCallbacks) {
mCallbacks.remove(mCallback.asBinder());
}
onCallbackDied(mCallback, mCookie);
}
}
/******其他代碼省略*******/
}
想閱讀作者的更多文章滋尉,可以查看我 個人博客 和公共號: