最近打算把Android基础的一些知识再深入一点,所以就打算从四大组件开始入手,广播是经常使用的,但是也仅仅只停留在会用,却不知其原理,就着这个机会把源码给撸一遍吧。
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(broadcastReceiver, new IntentFilter("broadcast_test"));
sendBroadcast(new Intent("broadcast_test"));
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("broadcast_test")){
Log.d("broadcast","receice");
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
}
本文不打算讲解广播的使用方法,就直接从动态注册广播开始好了,涉及到的源码为Android API 23。
上面demo中的registerReceiver(broadcastReceiver, new IntentFilter("broadcast_test"))执行的是ContextWrapper的方法:
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextWrapper的真正方法实现类为ContextImpl,也就是说mBase是ContextImpl的实例,对于这一块不是很了解的朋友可以看郭霖大神的这篇博客Android Context完全解析,你所不知道的Context的各种细节,由于这部分源码很多加了/** {@hide} */的注释,所以在Android Studio里面不能直接看到相关代码,我们要到SDK的路径\sdk\sources\android-23\android\app\下去查看相关代码。
class ContextImpl extends Context {
/*省略其它无关代码*/
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();//获取主线程的Handler
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}