Context 是 Android 系统提供的 全局环境信息接口,用于管理 应用资源、组件交互、系统服务访问 等。主要作用包括:
- 访问资源(getResources()、getAssets())
- 启动组件(startActivity()、startService()、sendBroadcast())
- 管理应用信息(getPackageManager()、getPackageName())
- 访问系统服务(getSystemService())
- 操作 SharedPreferences(getSharedPreferences())
- 创建视图(LayoutInflater.from(context))
Context 知识图谱
kotlin
Context(抽象类)
│
├── ContextWrapper(mBase)
│ ├── ContextThemeWrapper(带主题的封装类)
│ │ ├── Activity
│ │
│ ├── Service
│ │
│ ├── Application
│ │
│ ├──MutableContextWrapper(动态改变context)
│ │
├── ContextImpl (Context的实现类,系统底层实现)
Activity、Service、Application都是继承自ContextWrapper,而ContextWrapper又继承自Context,所以一个App中 Context的数量 = Activity数量 + Service数量 + 1(Application)
。
kotlin
//ContextWrapper.java
public class ContextWrapper extends Context {
@UnsupportedAppUsage
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
//......
}
Context采用装饰者模式,ContextWrapper是Context子类,内部都会调用传入的mBase相关方法(mBase其实就是ContextImpl),而Activity、Service、Application都是ContextWrapper的子类,所以它们都是跟ContextImpl关联的。
kotlin
┌──────────────┐
│ Context (抽象类) │
└──────┬──────┘
│
┌─────────────┴────────────┐
│ │
▼ ▼
┌──────────────┐ ┌─────────────────┐
│ ContextImpl │ │ ContextWrapper │
│ (真正实现) │ │ (持有 mBase 代理) │
└──────────────┘ └────────┬────────┘
│
▼
┌──────────────────────────┐
Activity / Service / Application 等 │
└──────────────────────────┘
Context/ContextWrapper/ContextImpl 三者关系:ContextWrapper、ContextImpl继承自Context,其中ContextImpl 是 Context 的具体实现,ContextWrapper 作为包装类持有 Context(通常是 ContextImpl),对其进行代理和扩展。
下面一起来看下Application、Activity、Service都是如何初始化并绑定Context的吧。
Application
kotlin
//ActivityThread.java
//系统进程(SystemServer)创建ActivityThread并初始化
public static ActivityThread systemMain() {
ThreadedRenderer.initForSystemProcess();
ActivityThread thread = new ActivityThread();
thread.attach(true, 0);
return thread;
}
//应用进程创建ActivityThread并初始化
public static void main(String[] args) {
//...其他代码...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
main() 用于应用进程启动ActivityThread,并进入 Looper 消息循环,确保主线程可以处理消息,并且执行了thread.attach方法。
kotlin
//ActivityThread.java
private void attach(boolean system, long startSeq) {
//应用测试和生命周期管理的核心组件,负责拦截 Activity 生命周期回调(如 onCreate())
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
//1、创建应用的 Context
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
//2、实例化 Application 对象
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
//调用application的onCreate()进行初始化
mInitialApplication.onCreate();
}
上面代码中有两个个主要操作,1处是创建应用的Context,也就是创建ContextImpl:
kotlin
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
String opPackageName) {
//...忽略其他代码...
//创建应用的Context
ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
ContextParams.EMPTY, null, null, null, null, null, 0, null, opPackageName);
context.setResources(packageInfo.getResources());
//...忽略其他代码...
return context;
}
2处是通过makeApplication()通过反射初始化了Application:
kotlin
//Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
//AppComponentFactory.java
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//通过反射初始化Application
return (Application) cl.loadClass(className).newInstance();
}
//Application.java
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
可以看到最终是在Application#attach()
方法中调用父类ContextWrapper#attachBaseContext()
来设置context。
Activity
Activity 继承 ContextThemeWrapper(拥有界面主题和窗口管理能力)。可以 启动 UI 相关组件(如 Dialog、startActivity())。
AMS (ActivityManagerService) 请求应用进程创建Activity时,ActivityThread#performLaunchActivity()
是启动Activity时的核心方法,主要完成了 Activity 的创建、绑定 Application、执行 attach() 等逻辑。
kotlin
//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
//ContextImpl是Activity运行所需的真正Context,并用于后续的attach()绑定。
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//通过反射机制创建Activity对象。
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
} catch (Exception e) {
}
try {
//Application只会在应用首次启动时创建一次,并在所有Activity之间共享
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
appContext.setOuterContext(activity);
//绑定各种信息,具体见下面说明
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken, r.shareableActivityToken);
}
} catch (SuperNotCalledException e) {
throw e;
}
return activity;
}
上面代码中的注释很详细,可以看到Activity初始化后,通过attach()
方法绑定各种信息,那就继续看看这个方法都做了什么。
kotlin
//Activity.java
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
IBinder shareableActivityToken) {
//这里调用的是父类ContextWrapper中的方法,将context赋值给父类的mBase
attachBaseContext(context);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mUiThread = Thread.currentThread();
//获取application
mApplication = application;
mIntent = intent;
//...省略部分代码...
}
attach()
绑定了各种信息,主要完成如下:
- 绑定 Context(将 Activity 绑定到 ContextImpl)
- 绑定 AMS(ActivityManager)
- 绑定 Application 实例
- 绑定 Window 和 PhoneWindow(管理 UI 视图)
- 初始化 Activity 相关参数
这一步完成后,Activity 就拥有了 Context,能够调用 getApplicationContext()
、getResources()
等方法。
Service
当 AMS (ActivityManagerService) 请求应用进程创建 Service 时,会调用ActivityThread#handleCreateService()
在应用进程中创建 Service 并完成初始化。
kotlin
//handleCreateService()负责创建并启动Service
private void handleCreateService(CreateServiceData data) {
Service service = null;
//LoadedApk 代表 APK 在内存中的加载信息,用于创建 Application 和 Service
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Application app = packageInfo.makeApplication(false, mInstrumentation);
final java.lang.ClassLoader cl;
//获取类加载器ClassLoader
if (data.info.splitName != null) {
cl = packageInfo.getSplitClassLoader(data.info.splitName);
} else {
cl = packageInfo.getClassLoader();
}
//反射创建Service实例
service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);
//创建Service的Context
ContextImpl context = ContextImpl.getImpl(service.createServiceBaseContext(this, packageInfo));
//绑定Context到Service,让Service可以访问 Context
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用service的onCreate()方法
service.onCreate();
//...通知AMS,Service已经启动完成...
}
可以看到Service的创建过程跟上面的Application、Activity都很类似。
MutableContextWrapper
MutableContextWrapper继承自ContextWrapper,提供了 setBaseContext(Context base) 方法,允许在运行时更改 Context,而不像ContextWrapper那样只能在创建时指定Context。关于MutableContextWrapper的详细介绍后面单独整理一篇。
Context 选择指南

- Application Context 适用于 全局管理,避免 Activity 相关的 内存泄漏。
- Activity Context 适用于 界面相关操作(如 Dialog、startActivity())。
- Service、BroadcastReceiver、ContentProvider 也可以使用 Context,但要 注意生命周期管理。
扩展
getApplicationContext 和 getApplication() 的区别
尽管在当前的 Android Activity 和 Service 实现中,getApplication() 和 getApplicationContext() 返回的是同一个对象,但并不能保证它们始终如此(例如,在某些特定厂商的实现中可能有所不同)。因此,如果想获取 Manifest 中注册的 Application 类,不应该调用 getApplicationContext() 并将其强制转换为Application,因为它可能并不是实际的Application 实例(在测试框架中可能已经遇到过这个问题)。那么 getApplicationContext() 为什么会存在呢?
getApplication() 仅在 Activity 和 Service 类中可用,而 getApplicationContext() 是在 Context 类中声明的。这意味着:
- 在 BroadcastReceiver 代码中,无法直接调用 getApplication(),因为 BroadcastReceiver 本身不是 Context,它只能通过 onReceive 方法获得 Context。
- 这也意味着,在 BroadcastReceiver 中无法保证可以访问 Application 实例,因此只能使用 getApplicationContext()。
当查看 Android 代码时,可以发现:
- Activity 在被 attach 时,会接收一个 baseContext 和 Application,这两个是不同的参数。
- getApplicationContext() 实际上是委托 baseContext.getApplicationContext() 来获取 Application 实例。
来自stackoverflow :stackoverflow.com/questions/5...