Android中Context的继承关系详解

原文地址:https://www.jianshu.com/p/b68276bb2f33

 

简介

  • Context在Android中表明上下文环境,可以用来启动Activity,开启服务,获取应用信息等作用。

继承关系

Android中的Context.png

Context

  • Context是一个抽象类,内部定义很多抽象类,包括startActivity,startService ,getResource 等方法

ContextImpl

  • ContextImpl继承Context,是Context的具体实现类

ContextWrapper

  • ContextWrapper是Context的包装类,是对外提供的接口类,继承Context,实现抽象方法,实现的方法交由ContextImpl来实现。
  • 其中attachBaseContext()是建立与ContextImpl的联系的桥梁。

ContextImpl和ContextWrapper的关系

  • 两者的关系 ,可以看作成是代理模式,ContextImpl代理ContextWrapper,Context是代理接口!

ContextThemeWrapper Service Application

  • 三者都是继承ContextWrapper
  • 其中ContextThemeWrapper是带有主题的Context

Activity

  • Activity是继承ContextThemeWrapper

ContextWrapper中的源码以及mBase

 

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();
    }

    @Override
    public Looper getMainLooper() {
        return mBase.getMainLooper();
    }

    @Override
    public Executor getMainExecutor() {
        return mBase.getMainExecutor();
    }

    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }
    
    @Override
    public void setTheme(int resid) {
        mBase.setTheme(resid);
    }

    /** @hide */
    @Override
    @UnsupportedAppUsage
    public int getThemeResId() {
        return mBase.getThemeResId();
    }

    @Override
    public Resources.Theme getTheme() {
        return mBase.getTheme();
    }

    @Override
    public ClassLoader getClassLoader() {
        return mBase.getClassLoader();
    }

    @Override
    public String getPackageName() {
        return mBase.getPackageName();
    }

    /** @hide */
    @Override
    @UnsupportedAppUsage
    public String getBasePackageName() {
        return mBase.getBasePackageName();
    }

    

    @Override
    public ApplicationInfo getApplicationInfo() {
        return mBase.getApplicationInfo();
    }
    
    @Override
    public String getPackageResourcePath() {
        return mBase.getPackageResourcePath();
    }

    @Override
    public String getPackageCodePath() {
        return mBase.getPackageCodePath();
    }

    @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        return mBase.getSharedPreferences(name, mode);
    }

    /** @removed */
    @Override
    public SharedPreferences getSharedPreferences(File file, int mode) {
        return mBase.getSharedPreferences(file, mode);
    }

    /** @removed */
    @Override
    public File getSharedPreferencesPath(String name) {
        return mBase.getSharedPreferencesPath(name);
    }

   
    @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }

    /** @hide */
    @Override
    public void startActivityAsUser(Intent intent, UserHandle user) {
        mBase.startActivityAsUser(intent, user);
    }

    /** @hide **/
    public void startActivityForResult(
            String who, Intent intent, int requestCode, Bundle options) {
        mBase.startActivityForResult(who, intent, requestCode, options);
    }
  • 在ContextWrapper中可以看见我们熟悉的方法 startActivity,gegetSharedPreferencest,getPackageInfo,getSystemInfo等一系列方法
  • 在这些方法都交由mBase来处理了

mBase

 

public ContextWrapper(Context base) {
        mBase = base;
    }
    
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
  • mBase的赋值可以有构造方法和attachBaseContext()方法来进行
  • 这里的mBase实则是ContextImpl,在调用atatchBaseContext()方法的时候,实则传递的是ContextImpl的实例。

几个问题

  • 一个应用中Context的数量?

Activity数量+Service数量+Application数量(通常为1,一个进程中只有一个Application)

  • getApplication()和getApplicationContext()的关系

两者获取的都是应用程序的Application对象,获取到的是同一个对象
getApplication() 通常用于Service,Activity 中,而getApplicationContext()用于比如BroadcastReceiver中获取Application
getApplicationContext同时也是ContextWrapper中的,相比较于getApplication(),getApplicationContext的作用域更广一些,getApplication()从语意上看,更强一些就是用于获取Application

  • 自定义的Application 对外提供实例不需要做多重检查了?

Application本身是单利,全局就仅仅有一个,不需要进行多重检查了,哈哈哈!

  • 能在自定义Application的构造方法中 调用实现Context中的抽象方法吗?

不可以的,会报错;
因为 Application是继承ContextWrapper的,而ContextWrapper中实现的抽象方法是交由ContextImpl来实现的,ContextImpl的获取是交由内部的attachBaseContext的,如果在构造方法中调用实现的抽象方法,会报错的,此时mBase为null

不能在构造方法中调用实现的抽象方法,可以在 attachBaseContext(){super() 之后调用},也可以在onCreate中调用



 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值