Android - 认识Context

app开发中,咱们须要使用app的资源,好比文字、图片,Activity、Service或者broadcastReceiver等等。时常也会用到getApplicationContext()来获取一个Context对象。那么这个Context究竟是什么呢?java

咱们一块儿来认识一下Android中的Context。本文主要内容以下图。android

Android-认识Context.png

Context类简介

context含义有语境,上下文,背景,环境等等。 Context是维持Android程序中各组件可以正常工做的一个核心功能类。git

Context是一个抽象类。它是一个 app 全局环境的“接口”,由 Android 系统提供继承类(例如Activity、Service、Application等)。它能链接到应用的资源,也能使用应用级的操做,好比启动activity,广播和接收intent。github

应用程序中Context的总数目为: 总Context个数 = Activity个数 + Service个数 + 1(Application Context)bash

Context的子类

简单的继承关系示意

Android-Context-class-Inheritance.png

Context
├── ContextImpl
└── ContextWrapper
    ├── Application
    ├── ContextThemeWrapper
    │   └── Activity
    └── Service
复制代码

从继承关系图中能够看出,Application类、Service类和Activity类都继承了Context类。应用程序被启动后,会为应用程序建立一个全局的Application对应的Context对象。ContextImpl类是Context的真正实现。ContextWrapper类是封装类。能够在不改变ContextImpl的状况下,为其增长一些自定义操做。ContextWrapper中的mBase其实是一个ContextImpl对象。而ContextImpl类中的mOuterContext是一个Context对象,指向相对应的Activity或Service或Application。app

ContextImpl

Context 是一个抽象类,子类 ContextImpl 实现了Context的方法;为Activity和其余应用组件提供基本的context对象。 ContextImpl.java (frameworks\base\core\java\android\app)ide

/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */
class ContextImpl extends Context { /*...*/ }
复制代码

ContextWrapper

Wrapper 有封装的意思;ContextWrapper是Context的封装类 。这里使用了装饰者模式,构造方法中传入了一个Context 实例。ContextWrapper持有ContextImpl对象。能够在不改变ContextImpl的状况下增长一些操做。post

ContextWrapper.java (frameworks\base\core\java\android\content)spa

/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */
public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    // ...
}
复制代码

具体操做中,Application类、Activity和Service类与ContextImpl产生交集。.net

ContextThemeWrapper

容许在封装的context中修改主题(theme)

ContextThemeWrapper.java (frameworks\base\core\java\android\view)

/** * A ContextWrapper that allows you to modify the theme from what is in the * wrapped context. */
public class ContextThemeWrapper extends ContextWrapper { /* ... */ }
复制代码

其中提供了关于theme的方法,app开发中 android:theme 与此有关。相同的代码,相同的调用,使用不一样的 theme 会有不一样的效果。

getApplicationContext() 和 getBaseContext()

public class ContextWrapper extends Context {
    Context mBase;
    ......
    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }
    ......
    /** * @return the base context as set by the constructor or setBaseContext */
    public Context getBaseContext() {
        return mBase;// Don't use getBaseContext(), just use the Context you have.
    }
    ......
}
复制代码
getApplicationContext() = android.app.Application@39d42b0e
getBaseContext() = android.app.ContextImpl@1f48c92f
复制代码

getApplicationContext() 从application取得context。getBaseContext() 从实现类ContextImpl那得来。

Context子类建立流程

Application的建立流程

咱们把关注点先放在application上,暂时忽略源码中的其余信息。

Android-Context-Application-flow.png

流程描述:

LoadedApk先经过classLoaderloadClass(className)获取application的class,再经过clazz.newInstance()建立Application实例。接着调用app.attach(context)方法完成初始化。 Application的attach方法里调用了本身的attachBaseContext(context), 把第一步建立的ContextImpl实例赋值给ContextWrappermBase成员变量。 到此Application实例建立就完成了。

Activity的建立 - performLaunchActivity

这里关注的是Activity的实例化以及以前的一些准备过程。

Android-Context-performLaunchActivity-flow.png

流程简析:

主要关注ActivityThreadperformLaunchActivity方法。经过ContextImplcreateActivityContext得到一个ContextImpl实例,称为appContextInstrumentationnewActivity返回了一个Activity实例。LoadedApk.makeApplication能够得到当前的application,若是当前没有则新建一个application。最后经过ContextImpl.setOuterContext和Activity的attach方法,将ContextImpl实例与Activity实例关联到一块儿。

使用

自定义Application

新建一个MyApplication类,继承自Application

import android.app.Application;
import android.content.Context;

public class MyApplication extends Application {
    private static Context context;

    public static Context getMyContext() {
        return context;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
}
复制代码

在Manifest中使用MyApplication;

<application android:name="com.rust.aboutview.MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
    ......
复制代码

便可在不一样的地方调用 getMyContext() 方法

MyApplication.getMyContext()
复制代码

参考

blog.csdn.net/yanbober/ar…

xujiaojie.github.io/2017/09/18/…

xujiaojie.github.io/2017/09/18/…

juejin.im/post/5c37f4…

相关文章
相关标签/搜索