Context完全解析(一)什么是Context?

   Context字面意思是上下文环境 ,它 是一个抽象类,定义很多访问应用程序环境中全局信息的接口,其正在的实现是在ContextImpl类中。 通过它可以访问应用程序的资源和相关的类,比如:Resources,AssetManager,Package,权限等相关信息;以及调用应用程序级的操作,比如: 启动Activity, 启动Service,发送广播,接收Intent等。

    下面是Context的继承关系图:



    从图中可以看出,Context的直接子类有两个,一个是ContextWrapper,一个是ContextImpl,从名字上就可以看出,ContextWrapper是上下文功能的包装类,而ContextImpl则是上下文功能的实现类。那么, ContextWrapper类中的变量mBase是 一 个Contextlmpl对象,而Contextlmpl的变量mOuterContext则是 一 个ContextWrapper对象。所以, 当我们在应用程序中调用 Context的方法时, 实际 调用的是 个Contextlmpl对象的方法,  这里用到了代理模式。
     ContextWrapper又有三个直接的子类,ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一个带主题的包装类,而它有一个直接子类就是Activity。所以,Context一共有Application、Activity和Service三种类型,因此一个应用程序中Context的数量是:Activity数量+Service数量+1。
    在分析它们的创建过程之前, 首先从代码的角度来看看这几个类的继承关系。

public abstract class Context {
    ......
    //可以获取各种资源:string,color,drawable等等   
    public abstract AssetManager getAssets();

    public abstract Resources getResources();

    /** Return PackageManager instance to find global package information. */
    public abstract PackageManager getPackageManager();

    /** Return a ContentResolver instance for your application's package. */
    public abstract ContentResolver getContentResolver();

    public abstract Looper getMainLooper();

    public abstract Context getApplicationContext();

    ......
    /**
     * Return the Theme object associated with this Context.
     */
    @ViewDebug.ExportedProperty(deepExport = true)
    public abstract Resources.Theme getTheme();
    
    //数据存储相关:数据库,文件,偏好等存储方式,可以获取资源文件存储路径等
    ......
    public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);
    ......
    public abstract FileOutputStream openFileOutput(String name, @FileMode int mode)
        throws FileNotFoundException;
    ......
    public abstract SQLiteDatabase openOrCreateDatabase(String name,
            @DatabaseMode int mode, CursorFactory factory);
    ......
    //启动四大组件相关:activity,service,Broadcast   
    public abstract void startActivity(@RequiresPermission Intent intent);
    ......
    public abstract void sendBroadcast(@RequiresPermission Intent intent);
    ......
    @Nullable
    public abstract ComponentName startService(Intent service);
    ......

    //启动系统各种服务:WindowManager,ActivityManager,AudioManager等几十个服务
    public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
    ......
    //应用权限相关
    @CheckResult(suggest="#enforcePermission(String,int,int,String)")
    @PackageManager.PermissionResult
    public abstract int checkPermission(@NonNull String permission, int pid, int uid);
    ......
    // 返回一个新的与application name对应的Context对象 
    public abstract Context createPackageContext(String packageName, 
            int flags) throws PackageManager.NameNotFoundException; 
     
    // 返回基于当前Context对象的新对象,其资源与display相匹配 
    public abstract Context createDisplayContext(Display display); 
    ......
    //跨进程通信相关
    public IBinder getActivityToken() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    @Nullable
    public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler,
            int flags) {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    public IApplicationThread getIApplicationThread() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    ......
}

      以上列举的是Context抽象类中定义的主要方法,下面看看ContextImpl关键成员和函数

class ContextImpl extends Context {
    ......
    final @NonNull ActivityThread mMainThread;//代表一个主线程实例
    final @NonNull LoadedApk mPackageInfo;//每一个packageName对应一个,单例的
    private @Nullable ClassLoader mClassLoader;//LoadedApk创建

    private final @Nullable IBinder mActivityToken;
    ......
    //Resources和Display都是由ResourcesManager来创建的mResourcesManager是单例
    private final @NonNull ResourcesManager mResourcesManager;
    private @NonNull Resources mResources;
    private @Nullable Display mDisplay; 

    private Context mOuterContext;//指向的是一个ContextWrapper对象
    ......
    private PackageManager mPackageManager;//单例,所有Context中都是同一对象
    ......
    
    private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
            @NonNull LoadedApk packageInfo, @Nullable String splitName,
            @Nullable IBinder activityToken, @Nullable UserHandle user, int flags,
            @Nullable ClassLoader classLoader) {
       ......
    }

}

     ContextImpl实现类中涉及的主要核心类是:ActivityThread,LoadedApk,PackageManager,ResourcesManager,这几个类都是单例的,一个应用程序进程中是共用同一个对象。其实Contextlmpl是 一 种轻量级类, 而Packagelnfo是 一 个重量级类,Contextlmpl中的大多数进行包操作的重量级函数实际上都是转向了mPackagelnfo对象相应的方法下来来看看其子类ContextWrapper的具体实现

public class ContextWrapper extends Context {
    Context mBase;//mBase 是一个 ContextImpl实例

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
    
    public Context getBaseContext() {
        return mBase;
    }

    @Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }
    //下面这些所实现的Context中抽象方法都是调用mBase中对应方法
    ......
}
     mBase 是一个 ContextImpl实例, 一般在创建 Application、Service和Activity 时,通过attachBaseContext给它赋值。并且,
ContextWrapper中定义的所有方法,都是实现其抽象父类中的方法,并且在方法内部调用的是mBase中对应方法,可以看出这个类使用的是代理设计模式。
public class ContextThemeWrapper extends ContextWrapper {
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private Configuration mOverrideConfiguration;
    private Resources mResources;
    ......
    public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
        super(base);
        mThemeResource = themeResId;
    }

    public ContextThemeWrapper(Context base, Resources.Theme theme) {
        super(base);
        mTheme = theme;
    }
    ......
}
   ContextThemeWrapper类内部包含了主题(Theme)相关的接口,即android:theme属性指定的, 只有Activity需要主题,Service不需要主题, 所以Service直接继承于ContextWrapper类。 Activity类 、Service类 、Application类本质上都是一个Context, 除了基于 Context类外, 还实现 了 一 些其他重要接口, 所实现的其他接口只是为了扩充Context的功能而 已,扩充后的类称之为 一 个Activity,Service,或者Application。



  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值