简介
- Context在Android中表明上下文环境,可以用来启动Activity,开启服务,获取应用信息等作用。
继承关系
Context
- Context是一个抽象类,内部定义很多抽象类,包括startActivity,startService ,getResource 等方法
ContextImpl
- ContextImpl继承Context,是Context的具体实现类
ContextWrapper
- ContextWrapper是Context的包装类,是对外提供的接口类,继承Context,实现抽象方法,实现的方法交由ContextImpl来实现。
- 其中attachBaseContext()是建立与ContextImpl的联系的桥梁。
ContextImpl和ContextWrapper的关系
- 两者的关系 ,可以看作成是代理模式,ContextImpl代理ContextWrapper,Context是代理接口!
ContextThemeWrapper Service Application
- 三者都是继承ContextWrapper
- 其中ContextThemeWrapper是带有主题的Context
Activity
- Activity是继承ContextThemeWrapper
ContextWrapper中的源码以及mBase
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();
}
@Override
public Looper getMainLooper() {
return mBase.getMainLooper();
}
@Override
public Executor getMainExecutor() {
return mBase.getMainExecutor();
}
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
@Override
public void setTheme(int resid) {
mBase.setTheme(resid);
}
/** @hide */
@Override
@UnsupportedAppUsage
public int getThemeResId() {
return mBase.getThemeResId();
}
@Override
public Resources.Theme getTheme() {
return mBase.getTheme();
}
@Override
public ClassLoader getClassLoader() {
return mBase.getClassLoader();
}
@Override
public String getPackageName() {
return mBase.getPackageName();
}
/** @hide */
@Override
@UnsupportedAppUsage
public String getBasePackageName() {
return mBase.getBasePackageName();
}
@Override
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
}
@Override
public String getPackageResourcePath() {
return mBase.getPackageResourcePath();
}
@Override
public String getPackageCodePath() {
return mBase.getPackageCodePath();
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return mBase.getSharedPreferences(name, mode);
}
/** @removed */
@Override
public SharedPreferences getSharedPreferences(File file, int mode) {
return mBase.getSharedPreferences(file, mode);
}
/** @removed */
@Override
public File getSharedPreferencesPath(String name) {
return mBase.getSharedPreferencesPath(name);
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
/** @hide */
@Override
public void startActivityAsUser(Intent intent, UserHandle user) {
mBase.startActivityAsUser(intent, user);
}
/** @hide **/
public void startActivityForResult(
String who, Intent intent, int requestCode, Bundle options) {
mBase.startActivityForResult(who, intent, requestCode, options);
}
- 在ContextWrapper中可以看见我们熟悉的方法 startActivity,gegetSharedPreferencest,getPackageInfo,getSystemInfo等一系列方法
- 在这些方法都交由mBase来处理了
mBase
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
- mBase的赋值可以有构造方法和attachBaseContext()方法来进行
- 这里的mBase实则是ContextImpl,在调用atatchBaseContext()方法的时候,实则传递的是ContextImpl的实例。
几个问题
- 一个应用中Context的数量?
Activity数量+Service数量+Application数量(通常为1,一个进程中只有一个Application)
- getApplication()和getApplicationContext()的关系
两者获取的都是应用程序的Application对象,获取到的是同一个对象
getApplication() 通常用于Service,Activity 中,而getApplicationContext()用于比如BroadcastReceiver中获取Application
getApplicationContext同时也是ContextWrapper中的,相比较于getApplication(),getApplicationContext的作用域更广一些,getApplication()从语意上看,更强一些就是用于获取Application
- 自定义的Application 对外提供实例不需要做多重检查了?
Application本身是单利,全局就仅仅有一个,不需要进行多重检查了,哈哈哈!
- 能在自定义Application的构造方法中 调用实现Context中的抽象方法吗?
不可以的,会报错;
因为 Application是继承ContextWrapper的,而ContextWrapper中实现的抽象方法是交由ContextImpl来实现的,ContextImpl的获取是交由内部的attachBaseContext的,如果在构造方法中调用实现的抽象方法,会报错的,此时mBase为null
不能在构造方法中调用实现的抽象方法,可以在 attachBaseContext(){super() 之后调用},也可以在onCreate中调用