共计 3798 个字符,预计需要花费 10 分钟才能阅读完成。
APP 开发中,咱们须要应用 app 的资源,比方文字、图片,Activity、Service 或者 broadcastReceiver 等等。时常也会用到
getApplicationContext()
来获取一个 Context 对象。那么这个 Context 到底是什么呢?
Context 类简介
context 含意有语境,上下文,背景,环境等等。Context 是维持 Android 程序中各组件可能失常工作的一个外围性能类。
Context
是一个抽象类。它是一个 app 全局环境的“接口”,由 Android 零碎提供继承类(例如 Activity、Service、Application 等)。它能连贯到利用的资源,也能应用利用级的操作,比方启动 activity,播送和接管 intent。
应用程序中 Context 的总数目为: 总 Context 个数 = Activity 个数 + Service 个数 + 1(Application Context)
Context 的子类
简略的继承关系示意
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。
ContextImpl
Context
是一个抽象类,子类 ContextImpl
实现了 Context
的办法;为 Activity 和其余利用组件提供根本的 context 对象。ContextImpl.java (frameworks\base\core\java\android\app)
/**
* 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
的状况下减少一些操作。
ContextWrapper.java (frameworks\base\core\java\android\content)
/**
* 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
产生交加。
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 上,临时疏忽源码中的其余信息。
流程形容:
LoadedApk
先通过 classLoader
的 loadClass(className)
获取 application 的 class
,再通过 clazz.newInstance()
创立 Application
实例。接着调用 app.attach(context)
办法实现初始化。
Application 的 attach 办法里调用了本人的 attachBaseContext(context)
, 把第一步创立的 ContextImpl
实例赋值给 ContextWrapper
的 mBase
成员变量。到此 Application 实例创立就实现了。
Activity 的创立 – performLaunchActivity
这里关注的是 Activity 的实例化以及之前的一些筹备过程。
流程简析:
次要关注 ActivityThread
的 performLaunchActivity
办法。通过ContextImpl
的 createActivityContext
取得一个 ContextImpl 实例,称为 appContext
。Instrumentation
的 newActivity
返回了一个 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()
【Android 零根底入门教程视频参考】