美文网首页
和Context类关联的组件

和Context类关联的组件

作者: gczxbb | 来源:发表于2019-01-27 13:19 被阅读18次

    组件Context

    组件Activity、Service以及Application都和Context有关联。在android api23的源码中,他们的关系图。 组件与Context的关系.jpg

    他们都继承ContextWrapper,Activity中间还有一层和关于主题的的装饰者。在ContextWrapper类中,attachBaseContext方法,加载具体的被装饰对象,即ContextImpl。

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;//ContextImpl对象。
    }
    

    Activity、Service和Application的内部Context,都是通过上面方法初始化的。在Activity的attach方法时,调用该方法。实体通过ContextImpl的静态方法创建。

    static ContextImpl createActivityContext(ActivityThread mainThread,
                LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread, packageInfo, null, null, false,
                    null, overrideConfiguration, displayId);
    }
    

    该方法创建Activity内部的ContextImpl。Service和Activity一样,也是在attach方法调用attachBaseContext方法,创建ContextImpl的静态方法不同。

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        return new ContextImpl(null, mainThread,
                    packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
    }
    

    Application和Service的ContextImpl创建方法是一样的,也是调用createAppContext方法创建。Application的attach方法,attachBaseContext设置内部Context。

    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
    appContext.setOuterContext(app);
    

    ContextImpl的setOuterContext设置外部引用它的Context。
    下面看一下我们常用的几个方法,第一个是getApplicationContext方法。在自己的Activity,Service组件和Application中,调用该方法获取Context。

    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }
    

    调用的是ContextWrapper的方法,最终调用实体ContextImpl的方法。它是Context的抽象方法,看一下ContextImpl的实现。

    @Override
    public Context getApplicationContext() {
        return (mPackageInfo != null) ?
                    mPackageInfo.getApplication() : mMainThread.getApplication();
    }
    

    先从LoadedApk中获取Application,LoadedApk是空时再从ActivityThread中获取。在ContextImpl构造方法传入LoadedApk,它就不是空。LoadedApk内部的Application是在makeApplication方法创建时赋值,也就是我们创建的全局Application对象。
    ActivityThread内部Application,在handleBindApplication方法初始化。

    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;
    

    其实,它也是通过LoadedApk的makeApplication方法创建的Application。因此,getApplicationContext方法,本质是获取Application。
    第二个方法是getApplication方法,在Activity和Service中,返回内部Application,该引用在attach方法初始化,是全局Application对象。因此,getApplication方法,返回Activity或Service内部的Application对象。

    总结

    Activity、Service和Application他们都是Context类型,内部引用真正的实现类ContextImpl。
    Activity和其他两者创建ContextImpl的方法是不同的。
    getApplication和getApplicationContext的区别,getApplication是Activity和Service的方法,getApplicationContext的具体实现在ContextImpl。他们都会返回Application。


    其他组件的Context

    ContentProvider不继承Context,内部的Context在创建对象时传入。

    public ContentProvider(
                Context context,
                String readPermission,
                String writePermission,
                PathPermission[] pathPermissions) {
        mContext = context;
        mReadPermission = readPermission;
        mWritePermission = writePermission;
        mPathPermissions = pathPermissions;
    }
    

    BroadcastReceiver即不继承Context,内部也没有Context对象,在onReceive方法时传入。实现该方法时,可以使用Context的功能。

    public abstract void onReceive(Context context, Intent intent);
    

    View的Context

    除了组件外,视图也和Context有关,创建视图时,他们的构造方法都会传入Context,在Activity创建一个View,传入的this代表Activity组件。

    public View(Context context) {
        mContext = context;
        ...
    }
    

    View的getContext方法,当然也是返回内部的Context。在View中需要使用Context的一些方法,可能是Activity的方法,也可能是ContextImpl的实现方法。


    任重而道远

    相关文章

      网友评论

          本文标题:和Context类关联的组件

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