五的代码 service是有个独立进程的,也就是任何一个activity只要有action就可以bind到此service,如果有很多个activity都bind到了此service中,该怎么处理呢?RemoteCallbackList。可以参考ApiDemo中的 App/service/remote service binding。
service代码如下:
public class RemoteService extends Service {
/**
* This is a list of callbacks that have been registered with the
* service. Note that this is package scoped (instead of private) so
* that it can be accessed more efficiently from inner classes.
*/
final RemoteCallbackList<IRemoteServiceCallback> mCallbacks
= new RemoteCallbackList<IRemoteServiceCallback>();
int mValue = 0;
NotificationManager mNM;
@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Display a notification about us starting.
showNotification();
// While this service is running, it will continually increment a
// number. Send the first message that is used to perform the
// increment.
mHandler.sendEmptyMessage(REPORT_MSG);
}
@Override
public void onDestroy() {
// Cancel the persistent notification.
mNM.cancel(R.string.remote_service_started);
// Tell the user we stopped.
Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
// Unregister all callbacks.
mCallbacks.kill();
// Remove the next pending message to increment the counter, stopping
// the increment loop.
mHandler.removeMessages(REPORT_MSG);
}
@Override
public IBinder onBind(Intent intent) {
// Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking
// the Intent.
if (IRemoteService.class.getName().equals(intent.getAction())) {
return mBinder;
}
if (ISecondary.class.getName().equals(intent.getAction())) {
return mSecondaryBinder;
}
return null;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public void registerCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.register(cb);
}
public void unregisterCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.unregister(cb);
}
};
/**
* A secondary interface to the service.
*/
private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
public int getPid() {
return Process.myPid();
}
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString) {
}
};
@Override
public void onTaskRemoved(Intent rootIntent) {
Toast.makeText(this, "Task removed: " + rootIntent, Toast.LENGTH_LONG).show();
}
private static final int REPORT_MSG = 1;
}
首先把回调用RemoteCallbackList封装起来,bind的时候,调用aidl接口registerCallback,将回调函数加入到mCallbacks内
public void registerCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.register(cb);
}
执行回调的时候,一般如下,已beginBroadcast开始,以finishBroadcast作为完结,就像事务一样
// Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).valueChanged(value);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
mCallbacks.finishBroadcast();
再看onbind
@Override
public IBinder onBind(Intent intent) {
// Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking
// the Intent.
if (IRemoteService.class.getName().equals(intent.getAction())) {
return mBinder;
}
if (ISecondary.class.getName().equals(intent.getAction())) {
return mSecondaryBinder;
}
return null;
}
根据bind的intent的action不同,返回不同的binder,service里实现了2个aidl接口,即有2个binder,mBinder和mSecondaryBinder,mBinder负责注册和反注册回调,mSecondaryBinder负责获取进程id。client端要用2个不同的ServiceConnection都bindService获取service里的2个binder。
killprocess会导致onServiceDisconnected被调用,然后service重启,unbindService是不会导致onServiceDisconnected被调用的,参考文章service基础
RemoteCallbackList vs arrayList
When we use aidl ,we often use code like this:
RemoteCallbackList<IRemoteServiceCallback> mCallbacks
.
Can we use ArrayList<IRemoteServiceCallback> mCallbacks
?
It is a List
same as an ArrayList
so YES but you wouldn't want to as RemoteCallbackList
does extra things for you to name 1
Keeps track of a set of registered IInterface callbacks
and also
If a registered callback's process goes away, this class will take care of automatically removing it from the list. If you want to do additional work in this situation, you can create a subclass that implements the onCallbackDied(E) method.
all quotes from the Documentation