在写aidl 逻辑的时候遇到了beginBroadcast() called while already in a broadcast 意思是已经在广播中调用了
源码:
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;
}
}
也查询其他帖子,共两类观点:
1.是因为多个进程clieng同时请求server,其中一个任务阻塞,导致server接收任务的整个通道阻塞,所以会报异常。个人不认同这种观点,是因为beginBroadcast内部进行了锁处理。有锁就意味着本身就有多个任务要处理,remoteCallList本身就是为了处理client的callback的,所以不会再让你处理子任务之间线程关系。
2.还有一个观点是,上次的任务没有调用finishBroadcast(),所以报异常。个人赞同第二种。翻阅源码我们可以看到对mBroadcastCount该字段进行判断,这个字段由mCallbacks容器的size决定。而finishBroadcast方法也有锁,而且锁的对象是当前的容器mCallbacks,所以判断beginBroadcast()和finishBroadcast()是配套使用的。那为什么会出现该问题。
个人猜测:
是因为server在回调client的方法时可能发现异常,导致没有触发finishBroadcast(),所以导致资源没有回收,才会出现问题,建议大家好好review代码。
在finally处理finishBroadcast()方法
public static void sendMsgToClient(String packageName, String json) {
try {
int i = remoteCallbackList.beginBroadcast();
Log.d(TAG, "------------------sendMsgToClient: (i="+i+") json:" + json+" packageName:"+packageName);
while (i > 0) {
i--;
String cookie = (String) remoteCallbackList.getBroadcastCookie(i);
if (packageName.equals(cookie)) {
ClientCallback callback = remoteCallbackList.getBroadcastItem(i);
callback.onServerAction(json);
}
}
} catch (RemoteException e) {
e.printStackTrace();
}finally {
remoteCallbackList.finishBroadcast();
}
}