美文网首页
App里面有几个context?

App里面有几个context?

作者: 代码我写的怎么 | 来源:发表于2023-01-08 09:18 被阅读0次

    1.Context的继承关系

    想要弄清楚这个问题,我们得先搞清楚Context的继承关系,如下图所示

    Context是一个抽象类,应用里面的Application、service和Activity均是其子类。而对于ContextWrapper来说,所有Context的具体实现均交由ContextImpl,这里用到了桥接模式。

    public class ContextWrapper extends Context {
        Context mBase;//就是ContextImpl
        ......
    
        protected void attachBaseContext(Context base) {
            if (mBase != null) {
                throw new IllegalStateException("Base context already set");
            }
            mBase = base;
        }
    
        @Override
        public AssetManager getAssets() {
            return mBase.getAssets();
        }
    
        @Override
        public Resources getResources() {
            return mBase.getResources();
        }
    
        @Override
        public PackageManager getPackageManager() {
            return mBase.getPackageManager();
        }
    
        @Override
        public ContentResolver getContentResolver() {
            return mBase.getContentResolver();
        }
       .....
    }
    

    我们来看下几个子类的具体实现

    1.1 Application

    在注释1处创建了ContextImpl,注释2处调用newApplication,newApplication会调用attach函数,将ContextImpl attach到Application

    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
            if (mApplication != null) {
                return mApplication;
            }
    
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
    
            Application app = null;
    
            String appClass = mApplicationInfo.className;
            if (forceDefaultAppClass || (appClass == null)) {
                appClass = "android.app.Application";
            }
    
            try {
                java.lang.ClassLoader cl = getClassLoader();
                if (!mPackageName.equals("android")) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                            "initializeJavaContextClassLoader");
                    initializeJavaContextClassLoader();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
                //1.创建ContextImpl
                ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
                //2.newApplication里面会调用attach函数
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
                appContext.setOuterContext(app);
            } catch (Exception e) {
                if (!mActivityThread.mInstrumentation.onException(app, e)) {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    throw new RuntimeException(
                        "Unable to instantiate application " + appClass
                        + ": " + e.toString(), e);
                }
            }
            mActivityThread.mAllApplications.add(app);
            mApplication = app;
    
            if (instrumentation != null) {
                try {
                    instrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!instrumentation.onException(app, e)) {
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                            + ": " + e.toString(), e);
                    }
                }
            }
    
            // Rewrite the R 'constants' for all library apks.
            SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
            final int N = packageIdentifiers.size();
            for (int i = 0; i < N; i++) {
                final int id = packageIdentifiers.keyAt(i);
                if (id == 0x01 || id == 0x7f) {
                    continue;
                }
    
                rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
            }
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    
            return app;
        }
    

    1.2 Activity

    如以下代码所示,创建Activity,在注释1处创建了ContextImpl,然后在注释2处attach了,activity的attach函数最终会调用attachBaseContext。

        private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                        Context.CONTEXT_INCLUDE_CODE);
            }
    
            ComponentName component = r.intent.getComponent();
            if (component == null) {
                component = r.intent.resolveActivity(
                    mInitialApplication.getPackageManager());
                r.intent.setComponent(component);
            }
    
            if (r.activityInfo.targetActivity != null) {
                component = new ComponentName(r.activityInfo.packageName,
                        r.activityInfo.targetActivity);
            }
    
            //1.创建了一个ContextImpl
            ContextImpl appContext = createBaseContextForActivity(r);
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = appContext.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                r.intent.prepareToEnterProcess();
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(activity, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate activity " + component
                        + ": " + e.toString(), e);
                }
            }
    
            try {
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
                if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
                if (localLOGV) Slog.v(
                        TAG, r + ": app=" + app
                        + ", appName=" + app.getPackageName()
                        + ", pkg=" + r.packageInfo.getPackageName()
                        + ", comp=" + r.intent.getComponent().toShortString()
                        + ", dir=" + r.packageInfo.getAppDir());
    
                if (activity != null) {
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                    Configuration config = new Configuration(mCompatConfiguration);
                    if (r.overrideConfig != null) {
                        config.updateFrom(r.overrideConfig);
                    }
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                            + r.activityInfo.name + " with config " + config);
                    Window window = null;
                    if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                        window = r.mPendingRemoveWindow;
                        r.mPendingRemoveWindow = null;
                        r.mPendingRemoveWindowManager = null;
                    }
                    appContext.setOuterContext(activity);
                    //2.将ContextImpl attach到activity里面
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.configCallback);
    
                    if (customIntent != null) {
                        activity.mIntent = customIntent;
                    }
                    r.lastNonConfigurationInstances = null;
                    checkAndBlockForNetworkAccess();
                    activity.mStartedActivity = false;
                    int theme = r.activityInfo.getThemeResource();
                    if (theme != 0) {
                        activity.setTheme(theme);
                    }
    
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onCreate()");
                    }
                    r.activity = activity;
                }
                r.setState(ON_CREATE);
    
                mActivities.put(r.token, r);
    
            } catch (SuperNotCalledException e) {
                throw e;
    
            } catch (Exception e) {
                if (!mInstrumentation.onException(activity, e)) {
                    throw new RuntimeException(
                        "Unable to start activity " + component
                        + ": " + e.toString(), e);
                }
            }
    
            return activity;
        }
    

    1.3 Service

    如以下代码所示,attach的过程和activity类似

    private void handleCreateService(CreateServiceData data) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
    
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
    
            try {
                if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
                //1.创建ContextImpl
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                //2.将ContextImpl attach到service里面
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                service.onCreate();
                mServices.put(data.token, service);
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    

    2.其他的

    还有其他的组件如,BroadCastReciver和ContentProvider,均不继承自Context,他们所使用的Context都是在创建的时候传递进去的。

    2.1 BroadCastReciver

    在注释2处将Context传递给BroadcastReciver,我们可以看到在注释1处,获取到了Application的BaseContext,最后在OnReceive里面传递的是context.getReceiverRestrictedContext()。

    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 {
                app = packageInfo.makeApplication(false, mInstrumentation);
                //1.获取Application的BaseContext
                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 = packageInfo.getAppFactory()
                        .instantiateReceiver(cl, data.info.name, data.intent);
            } catch (Exception e) {
                if (DEBUG_BROADCAST) Slog.i(TAG,
                        "Finishing failed broadcast to " + data.intent.getComponent());
                data.sendFinished(mgr);
                throw new RuntimeException(
                    "Unable to instantiate receiver " + component
                    + ": " + e.toString(), e);
            }
    
            try {
                if (localLOGV) Slog.v(
                    TAG, "Performing receive of " + data.intent
                    + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + packageInfo.getPackageName()
                    + ", comp=" + data.intent.getComponent().toShortString()
                    + ", dir=" + packageInfo.getAppDir());
    
                sCurrentBroadcastIntent.set(data.intent);
                receiver.setPendingResult(data);
                //2.这里传递了context
                receiver.onReceive(context.getReceiverRestrictedContext(),
                        data.intent);
            } catch (Exception e) {
                if (DEBUG_BROADCAST) Slog.i(TAG,
                        "Finishing failed broadcast to " + data.intent.getComponent());
                data.sendFinished(mgr);
                if (!mInstrumentation.onException(receiver, e)) {
                    throw new RuntimeException(
                        "Unable to start receiver " + component
                        + ": " + e.toString(), e);
                }
            } finally {
                sCurrentBroadcastIntent.set(null);
            }
    
            if (receiver.getPendingResult() != null) {
                data.finish();
            }
        }
    

    2.2 ContentProvider

    在注释1处,将Context传递给ContentProvider

    private ContentProviderHolder installProvider(Context context,
                ContentProviderHolder holder, ProviderInfo info,
                boolean noisy, boolean noReleaseNeeded, boolean stable) {
            ContentProvider localProvider = null;
            IContentProvider provider;
            if (holder == null || holder.provider == null) {
                if (DEBUG_PROVIDER || noisy) {
                    Slog.d(TAG, "Loading provider " + info.authority + ": "
                            + info.name);
                }
                Context c = null;
                ApplicationInfo ai = info.applicationInfo;
                if (context.getPackageName().equals(ai.packageName)) {
                    c = context;
                } else if (mInitialApplication != null &&
                        mInitialApplication.getPackageName().equals(ai.packageName)) {
                    c = mInitialApplication;
                } else {
                    try {
                        c = context.createPackageContext(ai.packageName,
                                Context.CONTEXT_INCLUDE_CODE);
                    } catch (PackageManager.NameNotFoundException e) {
                        // Ignore
                    }
                }
                if (c == null) {
                    Slog.w(TAG, "Unable to get context for package " +
                          ai.packageName +
                          " while loading content provider " +
                          info.name);
                    return null;
                }
    
                if (info.splitName != null) {
                    try {
                        c = c.createContextForSplit(info.splitName);
                    } catch (NameNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
    
                try {
                    final java.lang.ClassLoader cl = c.getClassLoader();
                    LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
                    if (packageInfo == null) {
                        // System startup case.
                        packageInfo = getSystemContext().mPackageInfo;
                    }
                    localProvider = packageInfo.getAppFactory()
                            .instantiateProvider(cl, info.name);
                    provider = localProvider.getIContentProvider();
                    if (provider == null) {
                        Slog.e(TAG, "Failed to instantiate class " +
                              info.name + " from sourceDir " +
                              info.applicationInfo.sourceDir);
                        return null;
                    }
                    if (DEBUG_PROVIDER) Slog.v(
                        TAG, "Instantiating local provider " + info.name);
                    // XXX Need to create the correct context for this provider.
                    //1.attachInfo将Context传递给ContentProvider
                    localProvider.attachInfo(c, info);
                } catch (java.lang.Exception e) {
                    if (!mInstrumentation.onException(null, e)) {
                        throw new RuntimeException(
                                "Unable to get provider " + info.name
                                + ": " + e.toString(), e);
                    }
                    return null;
                }
            } else {
                provider = holder.provider;
                if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
                        + info.name);
            }
    
            ContentProviderHolder retHolder;
    
            synchronized (mProviderMap) {
                if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
                        + " / " + info.name);
                IBinder jBinder = provider.asBinder();
                if (localProvider != null) {
                    ComponentName cname = new ComponentName(info.packageName, info.name);
                    ProviderClientRecord pr = mLocalProvidersByName.get(cname);
                    if (pr != null) {
                        if (DEBUG_PROVIDER) {
                            Slog.v(TAG, "installProvider: lost the race, "
                                    + "using existing local provider");
                        }
                        provider = pr.mProvider;
                    } else {
                        holder = new ContentProviderHolder(info);
                        holder.provider = provider;
                        holder.noReleaseNeeded = true;
                        pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                        mLocalProviders.put(jBinder, pr);
                        mLocalProvidersByName.put(cname, pr);
                    }
                    retHolder = pr.mHolder;
                } else {
                    ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
                    if (prc != null) {
                        if (DEBUG_PROVIDER) {
                            Slog.v(TAG, "installProvider: lost the race, updating ref count");
                        }
                        // We need to transfer our new reference to the existing
                        // ref count, releasing the old one...  but only if
                        // release is needed (that is, it is not running in the
                        // system process).
                        if (!noReleaseNeeded) {
                            incProviderRefLocked(prc, stable);
                            try {
                                ActivityManager.getService().removeContentProvider(
                                        holder.connection, stable);
                            } catch (RemoteException e) {
                                //do nothing content provider object is dead any way
                            }
                        }
                    } else {
                        ProviderClientRecord client = installProviderAuthoritiesLocked(
                                provider, localProvider, holder);
                        if (noReleaseNeeded) {
                            prc = new ProviderRefCount(holder, client, 1000, 1000);
                        } else {
                            prc = stable
                                    ? new ProviderRefCount(holder, client, 1, 0)
                                    : new ProviderRefCount(holder, client, 0, 1);
                        }
                        mProviderRefCountMap.put(jBinder, prc);
                    }
                    retHolder = prc.holder;
                }
            }
            return retHolder;
        }
    

    3.总结

    经过以上的分析,我们可以得出结论,应用里的context数量=Activity+Service+Application

    作者:我是黄大仙
    链接:https://juejin.cn/post/7180657897968238649

    相关文章

      网友评论

          本文标题:App里面有几个context?

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