
RemoteCallbackList 是 Android 提供的专门管理跨进程回调的容器。继续修改下RemoteService使用RemoteCallbackList管理跨进程回调替换掉那个ArrayList的callback容器。RemoteService代码如下package com.example.binderdemo; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; import java.util.List; public class RemoteService extends Service { private static final String TAG RemoteService; // private final ListICallback callbacks new ArrayList(); private final android.os.RemoteCallbackListICallback callbacks new android.os.RemoteCallbackList(); private final android.os.Handler handler new android.os.Handler(android.os.Looper.getMainLooper()); private final Runnable tick new Runnable() { Override public void run() { int n callbacks.beginBroadcast(); Log.d(TAG, tick, callbacks.size n); Log.d(TAG, tick, callbacks.size n , 何以解忧唯有退休); try { for (int i 0; i n; i) { ICallback cb callbacks.getBroadcastItem(i); try { cb.onResult(9527); } catch (RemoteException e) { Log.e(TAG, tick onResult failed: e); } } } finally { callbacks.finishBroadcast(); } handler.postDelayed(this, 3000); } }; Override public void onCreate() { super.onCreate(); Log.d(TAG, onCreate, start tick); handler.postDelayed(tick, 3000); } Override public void onDestroy() { Log.d(TAG, onDestroy, stop tick); handler.removeCallbacks(tick); super.onDestroy(); } private final IMyAidlInterface.Stub binder new IMyAidlInterface.Stub() { Override public int add(int a, int b) throws RemoteException { Log.d(TAG, add( a , b ) thread Thread.currentThread().getName() , pid Process.myPid()); int result a b; // 遍历回调beginBroadcast / getBroadcastItem / finishBroadcast int n callbacks.beginBroadcast(); try { for (int i 0; i n; i) { ICallback cb callbacks.getBroadcastItem(i); try { cb.onResult(result); } catch (RemoteException e) { Log.e(TAG, onResult failed: e); } } } finally { callbacks.finishBroadcast(); } return result; } Override public String getMessage() { Log.d(TAG, getMessage thread Thread.currentThread().getName() , pid Process.myPid()); return Hello from pid Process.myPid() , 为人不识陈近南纵称英雄也枉然。; } Override public void registerCallback(ICallback cb) throws RemoteException { if (cb null) return; Log.d(TAG, registerCallback cb cb , class cb.asBinder().getClass().getName() , thread Thread.currentThread().getName()); callbacks.register(cb); } Override public void unregisterCallback(ICallback cb) throws RemoteException { if (cb ! null) { callbacks.unregister(cb); } } }; Override public IBinder onBind(Intent intent) { Log.d(TAG, onBind thread Thread.currentThread().getName() , pid Process.myPid()); return binder; } }运行查看日志点击杀客户端进程按钮日志可以看出使用RemoteCallbackList管理callback比较方便其内部还兼顾了线程同步。而且客户端进程被杀掉后服务端自动清理callback。callbacks.size 自动变 0不需要写 binderDiedRemoteCallbackList 内部已经 linkToDeath 了。没有任何 DeadObjectException因为死回调在 tick 遍历之前已经被移除了。没有 ConcurrentModificationExceptionbeginBroadcast / finishBroadcast 的遍历快照机制生效了。onDestroy 在 60 秒后出现这是后台服务限制和 Binder 无关。比手动维护一个callback数组很有优势。ok.