一个Context意味着一个场景,一个场景就是用户和操作系统交互的过程。比如你打电话时,场景包括你打电话的界面,以及隐藏在界面后的数据。
Context到底是什么?
一个Activity是一个Context,一个Service也是一个Context。
我们先不看代码,而从语义的角度理解Context,Android程序员把场景抽象成Context类,它们认为用户和操作系统的每一次交互都是一个场景。比如打电话,发短信等这都是有界面的场景,而有些没有界面的场景:比如说Service。
从代码中可以看出。Activity类基于Context,而Service也是基于Context,Activity除了基于Context类外,还实现了一些其他的接口。从设计者的角度来讲,interface仅仅是某些功能,而extends才是类的本质。也就是说一个Activity是一个Context,一个Service也是一个Context。
为了使用方便,定义了ContextWrapper类,就是Context的包装类
Context的部分代码如下:
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
public Context getBaseContext() {
return mBase;
}
@Override
public AssetManager getAssets() {
return mBase.getAssets();
}
@Override
public Resources getResources()
{
return mBase.getResources();
}
@Override
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}
ContextThemeWrapper其内部包含了主题相关的接口。这里所说的主题就是在AndroidMainfest.xml文件中配置的android:theme。它可以是为Application或者Activity元素指定的主题。当然,Activity需要主题,而Service没有界面,运行在后台的,因此Service直接继承于ContextWrapper。
ContextThemeWrapper的部分源码:
public class ContextThemeWrapper extends ContextWrapper {
private int mThemeResource;
private Resources.Theme mTheme;
private LayoutInflater mInflater;
private Configuration mOverrideConfiguration;
private Resources mResources;
public ContextThemeWrapper() {
super(null);
}
public ContextThemeWrapper(Context base, int themeres) {
super(base);
mThemeResource = themeres;
}
@Override protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (mResources != null) {
throw new IllegalStateException("getResources() has already been called");
}
if (mOverrideConfiguration != null) {
throw new IllegalStateException("Override configuration has already been set");
}
mOverrideConfiguration = new Configuration(overrideConfiguration);
}
@Override
public Resources getResources() {
if (mResources != null) {
return mResources;
}
if (mOverrideConfiguration == null) {
mResources = super.getResources();
return mResources;
} else {
Context resc = createConfigurationContext(mOverrideConfiguration);
mResources = resc.getResources();
return mResources;
}
}
@Override public void setTheme(int resid) {
mThemeResource = resid;
initializeTheme();
}
}
Activity的个数+Service个数+1(Application)
一个应用程序在客户端都是从ActivityThread类开始的,创建Context也是在该类中完成具体创建ContextImpl类的地方一共有7处:
每一个应用程序在启动的时候都会创建一个Application对象,默认的Applicatin就是应用程序的包名。用户可以重载Application。方法是在AndroidManifest.xml文件的Application标签中声明一个新的Application名称,然后在源码中添加该类的名称。
启动Activity时,AmS通过IPC调用到ActivityThread的scheduleLaunchActivity()方法,然后调用到handlerLaunchActivity,最后调用到performLaunchActivity(),在该方法中创建了ContextImpl的代码如下:
ContextImple appContext=new ContextImpl();
appContext.init(r.packageInfo,r.token,this);
appContext.setOuter(activity);
ActivityInfo aInfo=r.activityInfo;
if(r.packageInfo==null){
r.packageInfo=getPackageInfo(aInfo.application);
Context.CONTEXT_INCLUDE_CODE;
}
即在performLaunchActivity()开始执行,首先为r.packageInfo变量赋值,packageInfo()方法执行的逻辑和getPackageInfoNoChecked()基本相同。所以,r.packageInfo对象的PackageInfo对象和Application对应的packageInfo对象是同一个对象。
Service对象Context与Activity创建的过程一样。我们平常说Service就是没有界面的Activity。