谈谈 Android 的 Context - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

谈谈 Android 的 Context

发表时间:2020-10-17

发布人:葵宇科技

浏览次数:43

一、背景

忙活了一年,最近工作终于有点时间闲下来学习一下。今天复习了一下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

分析源码

相关案例查看更多