美文网首页
BroadCastReceiver和ContentProvide

BroadCastReceiver和ContentProvide

作者: code希必地 | 来源:发表于2020-09-17 14:41 被阅读0次

1、BroadCastReceiver的Context

BroadCastReceiver分为动态注册和静态注册,这里先看下动态注册的过程,在Activity中动态注册的代码如下:

1.1、动态注册

 MyBroadCastReceiver2 myBroadCastReceiver2 = new MyBroadCastReceiver2();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("dynamic_regist");
        registerReceiver(myBroadCastReceiver2, intentFilter);

最终会调用Activity的父类ContextWrapperregisterReceiver()ContextWrapper是静态代理类,最终会交给目标类ContextImpl来调用registerReceiver()

@Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext(), 0);
    }

ContextImplregisterReceiver()又会调用其registerReceiverInternal()注意调用registerReceiverInternal()传入的ContextgetOuterContext()
getOuterContext()是什么呢?
Application、Activity、ServiceContext创建过程中,会创建Application、Activity、Service的实例以及ContextImpl的实例,然后调用ContextImpl.setOuterContext(Context context)Application、Activity、Service的实例传入到ContextImpl中并赋值给其成员变量mOuterContext具体可查看
Context关联类和Application Context创建过程
Activity和Service的Context的创建过程

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                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();
            }
        }
        //.....
    }

最终会调用mPackageInfo.getReceiverDispatcher()

 public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
            Context context, Handler handler,
            Instrumentation instrumentation, boolean registered) {
        synchronized (mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
            if (registered) {
                map = mReceivers.get(context);
                if (map != null) {
                    rd = map.get(r);
                }
            }
            if (rd == null) {
                rd = new ReceiverDispatcher(r, context, handler,
                        instrumentation, registered);
                if (registered) {
                    if (map == null) {
                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                        mReceivers.put(context, map);
                    }
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver();
        }
    }

在方法中会创建ReceiverDispatcher实例并把context赋值给ReceiverDispatcher的成员变量mContext进行保存。
当我们调用sendBroadcast(intent)发送广播时,会调用ReceiverDispatcherperformReceive()

public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

mActivityThread.post(args.getRunnable())会执行Runnable

public final Runnable getRunnable() {
                return () -> {
                    final BroadcastReceiver receiver = mReceiver;
                    final boolean ordered = mOrdered;
                    //.......
                    try {
                        //....
                        receiver.onReceive(mContext, intent);
                    } catch (Exception e) {
                        //....
                    }
                   //....
                };
            }

可以看到最终会调用receiver.onReceive(mContext, intent)并把注册时传入的mContext传递到onReceive()中。
总结:

  • 1、在Activity中动态注册广播,onReceive()中传入的Context是Activity本身。
  • 2、在Application中动态注册广播,onReceive()中传入的Context是Application本身。
  • 3、在Service中动态注册广播,onReceive()中传入的Context是Service本身。

1.2、静态注册

静态注册在应用安装时由系统完成注册,在分发时ApplicationThreadscheduleReceiver()

 public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                boolean sync, int sendingUser, int processState) {
            updateProcessState(processState, false);
            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
                    sync, false, mAppThread.asBinder(), sendingUser);
            r.info = info;
            r.compatInfo = compatInfo;
            sendMessage(H.RECEIVER, r);
        }

发送一个类型为H.RECEIVER消息到H中,在handleMessage()中会调用ActivityThreadhandleReceiver()

private void handleReceiver(ReceiverData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        String component = data.intent.getComponent().getClassName();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);

        IActivityManager mgr = ActivityManager.getService();

        Application app;
        BroadcastReceiver receiver;
        ContextImpl context;
        try {
            //创建Application
            app = packageInfo.makeApplication(false, mInstrumentation);
            //获取Application的ContextImpl
            context = (ContextImpl) app.getBaseContext();
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            java.lang.ClassLoader cl = context.getClassLoader();
            data.intent.setExtrasClassLoader(cl);
            data.intent.prepareToEnterProcess();
            data.setExtrasClassLoader(cl);
            //创建Receiver
            receiver = packageInfo.getAppFactory()
                    .instantiateReceiver(cl, data.info.name, data.intent);
        } catch (Exception e) {
            //....
        }

        try {
            //....
            sCurrentBroadcastIntent.set(data.intent);
            receiver.setPendingResult(data);
            //调用Receiver的onReceive
            receiver.onReceive(context.getReceiverRestrictedContext(),
                    data.intent);
        } catch (Exception e) {
           //....
        } finally {
            sCurrentBroadcastIntent.set(null);
        }
        if (receiver.getPendingResult() != null) {
            data.finish();
        }
    }

方法中会创建Receiver,并调用receiver.onReceive()onReceive()中传入的Context是通过context.getReceiverRestrictedContext()生成的,context是在创建Application时创建的ContextImpl实例,所以getOuterContext()返回的就是Application本身。

###ContextImpl
final Context getReceiverRestrictedContext() {
        if (mReceiverRestrictedContext != null) {
            return mReceiverRestrictedContext;
        }
        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
    }

###ReceiverRestrictedContext
class ReceiverRestrictedContext extends ContextWrapper {
    ReceiverRestrictedContext(Context base) {
        super(base);
    }
}

从上面代码可知getReceiverRestrictedContext()返回的是以ApplicationmBaseContextWrapper,注意这里的Context并不是Application,和动态注册是不一样的。

2、ContentProvider的Context

ContentProvider本身不是Context,但是它有一个成员变量mContext,是通过构造函数传入的。所以问题就在于ContentProvider何时创建的。
ContentProvider的创建是在Application创建时创建的,Application的创建逻辑是在ActivityThread.handleBindApplication()

private void handleBindApplication(AppBindData data) {
        //....
        Application app;
        try {
          //创建Application
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    //创建ContentProvider
                    installContentProviders(app, data.providers);
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }
            //....
            try {
                //调用Application的onCreate()
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
               //...
            }
        } finally {
            //....
        }

       //.....
    }

创建过程如下:

  • 1、在LoadedApk中创建Application
  • 2、调用installContentProviders(app, data.providers)将创建的Application传入创建ContentProvider
  • 3、调用ApplicationonCreate()
    installContentProviders(app, data.providers)
  private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
        final ArrayList<ContentProviderHolder> results = new ArrayList<>();

        for (ProviderInfo cpi : providers) {
            //遍历创建ContentProvider
            ContentProviderHolder cph = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }

      //....
    }

installProvider()

private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
       //....
            try {
                //...
                localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
               //....
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
               //....
            }
        } else {
            provider = holder.provider;
            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
                    + info.name);
        }
       //....
        return retHolder;
    }

方法中反射创建ConentProvider,并调用ConentProviderattachInfo()

private void attachInfo(Context context, ProviderInfo info, boolean testing) {
        
        if (mContext == null) {
            mContext = context;
            //....
            ContentProvider.this.onCreate();
        }
    }

attachInfo中将传入的contextApplication实例赋值给ContentProvidermContext

3、总结

  • 1、动态注册的广播:在注册时会创建ReceiverDispatcher的实例,并把getOutContext()赋值给其成员变量mContext,在收到广播时,会调用对应ReceiveronReceive()并将ReceiverDispatcher的成员变量mContext传入。所以在Activity、Service、Application中分别调用registReceiver()时,onReceive()中的Context分别是Activity、Service、Application的实例。
  • 2、静态注册广播:系统完成静态广播的注册,在收到通知时会创建Receiver然后调用其onReceive()并将以ApplicationmBaseContextWrapper传入。
  • 3、ContentProvider本身并不是Context只不过它有一个成员变量mContextContentProvider创建之后会调用其attachInfo(),在方法中将Application赋值给mContext

相关文章

网友评论

      本文标题:BroadCastReceiver和ContentProvide

      本文链接:https://www.haomeiwen.com/subject/xbzaektx.html