谈谈 Android 的 Context

一、背景

   忙活了一年,最近工作终于有点时间闲下来学习一下。今天复习了一下context的知识。看淡很多知识点都已经忘记了,或者是以前也没有理解透彻。这里复习一下。顺便总结 Context 的知识点。

前面学习了Activity的启动 ,在创建 从客户端进程的过程中 ,AMS会通知 ActivityThread 创建 Application ,并且调用 Application 的onCreate 方法。

这是一个应用进程中第一个我们常用的 Application 创建的地方,另外我们在项目中常见的 Context 还有 Activity、Service。

这些Context 有什么区别呢,下面我们来探讨一下。

二、Context 的类型的继承结构

Android 中有好几个Context ,其继承结构如下:

我们常见的Application 、Service 和 Activity 实际上都是集成至 ContextWrapper 

ContextImpl 和 ContextWrapper 都继承至Context,其中

ContextImpl :Context 的具体实现

ContextWrapper : 内部持有ContextImpl 对象,采用装饰者的模式对ContextImpl 进行装饰。

 

三、分析各个Context 

3.1、Context 分析

public abstract class Context

       上面可以看到 Context 类是一个抽象类,里边实现了各种抽象方法, 等待着集成类去实现。 在Android 系统中,整个Context的实现类的结构采用的就是
       装饰者模式,在 ContextImpl 集成并实现了Context的具体功能,在ContextWrapper中持有 ComtextImpl,并集成了Context 。
       Application、Activity、Service 都是继承至 ActextWrapper 。采用装饰者模式添加不同功能。

3.2、ContextImpl 创建

(1)ContextImpl 的集成结构

class ContextImpl extends Context

(2)应用进程 创建之后,AMS 通知 应用进程创建 Application ,并进入其中 onCreate 方法

private void handleBindApplication(AppBindData data) {
        ... ... 
		//这里可以清楚看到,ActivitThread 创建了一个 ContextImpl 
		//其中ContextImpl 才是真正的实现类,Context
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        ... ... 
        try {
            //创建Application  
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                List<ProviderInfo> providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

            try {
				//调用Application.onCreate() 方法 
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
		// 这重新new 了一个 ContextImpl 
        return new ContextImpl(null, mainThread,
                packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}

3.3、分析ContextWarpper

(1)

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

创建了 Application ,我们看看Application 的继承结构,他是继承至 ContextWrapper :

public class Application extends ContextWrapper implements ComponentCallbacks2

(2) ContextWrapper 的结构

public class ContextWrapper extends Context {
    Context mBase; //这里对应的就是ContextImpl 

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
	 //是所有的ContextWrapper 对象初始化的时候,都可以调用该方法和 ContextImpl 进行绑定 
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

	//获取 ContextImpl 
    public Context getBaseContext() {
        return mBase;
    }
	
	/// -------------- 下方列举了几个方法,都是直接调用了 mBase中的具体实现
	@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();
    }
	... ...
}

上面可以看到,Context Wrapper 中有一个mBase 的Context 对象,其实该对象就是 ContextImpl 。所有ContextWrapper的创建都要在构造函数 或者 调用 attachbaseContext 传入 ContextImpl .可以看看前面创建 Application的时候是如何。

(3)Application 创建

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        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")) {
                initializeJavaContextClassLoader();
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
			/**
			这里使用calss.newInstance 的方式创建一个新的 Application 
			创建之后调用 app.attachattach(context); 方法,把Application 和 ContextImpl 进行绑定 
			static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
				Application app = (Application)clazz.newInstance();
				app.attachattach(context);
				return app;
			}
			**/
			
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        ... ...
        return app;
    }

 上面可以看到,使用clasloader 创建了Application 之后,会调用 attachattach 方法把 Application 和 ContextImpl 绑定在一块。

 

3.4、Application 

public class Application extends ContextWrapper implements ComponentCallbacks2
Application 集成了ContextWrapper

3.5、Service

public abstract class Service extends ContextWrapper implements ComponentCallbacks2
Service 集成了ContextWrapper

3.6、ContextThemeWrapper

public class ContextThemeWrapper extends ContextWrapper
ContextThemeWrapper 集成了ContextWrapper

3.7、Activity 

public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback 

Activity 集成了 ContextThemeWrapper

3.8 、

上面的分析可以看到,
ContextImpl 才是context的具体实现 
我们项目进程接触到的 Context 都是集成了 ContextWrapper 
而ContextWrapper 是中绑定了 ContextImpl ,并且ContextWrapper是ContextImpl 的装饰者,其中所有的具体实现都是调用了 ContextImpl 

 

参考:

https://blog.csdn.net/guolin_blog/article/details/47028975

https://www.cnblogs.com/lianghe01/p/6442239.html

https://www.jianshu.com/p/dabaebe9574d

分析源码

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值