RemoteCallbackList 机制分析

来源:互联网 发布:linux thrift源码安装 编辑:程序博客网 时间:2024/06/03 22:45

前言:

RemoteCallbackList主要用于aidl的跨进程通信,并且主要是服务端回调客户端的方法。

回调的aidl文件如下,

package com.•••;interface ICallback {    void onGetservice(String info);}

主要分为2步,

private final RemoteCallbackList<ICallback> mRemoteCallbacks = new RemoteCallbackList<ICallback>();private ICallback mCallback;

1,客户端调用服务端方法时进行回调注册,

@Overridepublic void queryFwVersion(ICallback callback) throws RemoteException {      if (callback != null) {          mCallback = callback;          mRemoteCallbacks.register(callback);          •••    }}

2,服务端的回调,

final int N = mRemoteCallbacks.beginBroadcast();    for (int i = 0; i < N; i++) {//遍历逐个回调         try {              mRemoteCallbacks.getBroadcastItem(i). onGetservice (sa);         } catch (RemoteException e) {              e.printStackTrace();         }    }mRemoteCallbacks.finishBroadcast();mRemoteCallbacks.unregister(mCallback);

最后一般在onDestroy方法中会调用,

mRemoteCallbacks. kill()

这里一共涉及到6个方法,下面逐个分析。

1, register

RemoteCallbackList注册回调方法如下,

public boolean register(E callback) {     return register(callback, null);}

register方法如下,

public boolean register(E callback, Object cookie) {        synchronized (mCallbacks) {            if (mKilled) {                return false;            }            IBinder binder = callback.asBinder();            try {                Callback cb = new Callback(callback, cookie);                binder.linkToDeath(cb, 0);//监听客户端是否进程是否终止                mCallbacks.put(binder, cb);                return true;            } catch (RemoteException e) {                return false;            }        }    }

主要是将callback和对应的Ibinder对象放入mCallbacks哈希表中,定义如下,

ArrayMap<IBinder, Callback> mCallbacks  = new ArrayMap<IBinder, Callback>();

Ibinder对象主要是监听客户端是否终止。

Callback是RemoteCallbackList的内部类,主要是实现了binderDied方法, Callback定义如下,

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);      }}

如果远程客户端进程终止,则会回调binderDied方法, binderDied方法首先从mCallbacks中删除客户端的回调对象,

然后调用onCallbackDied方法, onCallbackDied其实是个空方法, RemoteCallbackList并未实现,当然服务端可以

覆盖实现,也可以不实现。

2 unregister

unregister方法和register方法刚好相反,

public boolean unregister(E callback) {      synchronized (mCallbacks) {          Callback cb = mCallbacks.remove(callback.asBinder());          if (cb != null) {               cb.mCallback.asBinder().unlinkToDeath(cb, 0);               return true;           }           return false;       }  }

unregister首先从mCallbacks中移除对应的Callback对策,然后解除客户端的监听,

3, beginBroadcast

beginBroadcast方法如下,

public int beginBroadcast() {        synchronized (mCallbacks) {            if (mBroadcastCount > 0) {                throw new IllegalStateException(                        "beginBroadcast() called while already in a broadcast");            }                        final int N = mBroadcastCount = mCallbacks.size();            if (N <= 0) {                return 0;            }            Object[] active = mActiveBroadcast;            if (active == null || active.length < N) {                mActiveBroadcast = active = new Object[N];            }            for (int i=0; i<N; i++) {                active[i] = mCallbacks.valueAt(i);            }            return N;        }    }

将mCallbacks 中元素的个数保存在mBroadcastCount变量中,

将mCallbacks 中元素逐个保存在mActiveBroadcast组中,当然通常mCallbacks仅有一个元素。

4, getBroadcastItem

public E getBroadcastItem(int index) {        return ((Callback)mActiveBroadcast[index]).mCallback;    }

getBroadcastItem根据下标获取mActiveBroadcast中的mCallback对象。

通常紧接着就调用其aidl方法。

5, finishBroadcast

public void finishBroadcast() {        if (mBroadcastCount < 0) {            throw new IllegalStateException(                    "finishBroadcast() called outside of a broadcast");        }                Object[] active = mActiveBroadcast;        if (active != null) {            final int N = mBroadcastCount;            for (int i=0; i<N; i++) {                active[i] = null;            }        }                mBroadcastCount = -1;    }

finishBroadcast方法将active中的元素置为空,然后将变量赋为-1.

6, kill

public void kill() {        synchronized (mCallbacks) {            for (int cbi=mCallbacks.size()-1; cbi>=0; cbi--) {                Callback cb = mCallbacks.valueAt(cbi);                cb.mCallback.asBinder().unlinkToDeath(cb, 0);            }            mCallbacks.clear();            mKilled = true;        }    }

将mCallbacks清空,并且将mKilled变量赋值为true。

其实, RemoteCallbackList类还是很简单的,

ArrayMap<IBinder, Callback> mCallbacks            = new ArrayMap<IBinder, Callback>();

mCallbacks变量主要保存客户端注册的Callback对象,并监听客户端进程的状态。

private Object[] mActiveBroadcast;

mActiveBroadcast保存mCallbacks中的元素,利于逐个变量。

private int mBroadcastCount = -1;private boolean mKilled = false;
mBroadcastCount保存mCallbacks中元素的个数,mKilled表示是否kill。