在Android上,ContentObserver原本的目的是方便监听插入数据库中的数据的变化的,不过可以利用它来跨进程通信。
ContentObserver的跨进程通信 稍稍有点像BroadcastReceiver,不过确实不一样。
跨进程的使用方法:
1. 先写一个类继承ContentObserver,这点跟BroadcastReceiver使用有些类似,它是继承BroadcastReceiver
public class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.e("test", "Uri = " + uri + " selfChange = " + selfChange);
}
}
2. 在某个地方注册监听某个Uri。而动态BroadcastReceiver也是注册(IntentFilter 中有条件)、
比如Uri为:Uri.parse("content://com.abc.xyz.MyProvider");
//需要注意的是uri必须得是一个具体的存在的ContentProvider
//第二个参数为true,表示可以同时匹配其派生的Uri,这点是这里说的跨进程通信的一个关键点
getContentResolver().registerContentObserver(uri, true, myObserver);
3. 在想发送消息的地方发送。而BroadcastReceiver是sendBroadcast(intent);
getContentResolver().notifyChange(uri, null);
第3步中Uri可以这么写:Uri.parse("content://com.abc.xyz.MyProvider/想要跨进程的内容");
这样通过第3步之后,第1步中的onChange中的uri变为String之后就可以得到 content://com.abc.xyz.MyProvider/想要跨进程的内容
可以看出,这里跨进程发送的内容只能是String类型的,使用的方式方法跟BroadcastReceiver有些类似。
总结一下,关键点:
1. Uri中的地址必须得是一个确实存在的ContentProvider;
2. registerContentObserver中的第二个参数为true;
3. 只能携带发送的内容是String类型;
大致的原理:
ContentObserver的底层原理还是使用Binder。
在registerContentObserver的时候,把ContentObserver中的内部Binder注册给系统服务ContentService;
而notifyChange的时候,也是通过系统服务ContentService,把Uri传递过去;
而ContentService根据registerContentObserver的Uri来进行匹配,并把符合条件的Uri发送给监听者ContentObserver。