Context及其子类:
这个家族一共有7个类:
Context就像应用程序的大管家,可以启动activity和service、调用资源和系统服务等。activity和application和service最终都继承context,所以APP内共有Context的数量为: Activity数量+Service数量+1个Application内的Context
Context源码:
public abstract class Context {
// 1,四大组件的交互:启动activity,发送广播,注册服务,获取ContentResolver
public abstract void startActivity(@RequiresPermission Intent intent);
public abstract void sendBroadcast(@RequiresPermission Intent intent);
public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
IntentFilter filter);
public abstract void unregisterReceiver(BroadcastReceiver receiver);
public abstract ComponentName startService(Intent service);
public abstract boolean stopService(Intent service);
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
public abstract void unbindService(@NonNull ServiceConnection conn);
public abstract ContentResolver getContentResolver();
// 2,获取系统/应用资源:包括AssetManager、Resources、PackageManager、ClassLoader、一些文件等
public abstract AssetManager getAssets();
public abstract Resources getResources();
public abstract PackageManager getPackageManager();
public abstract Context getApplicationContext();
public abstract ClassLoader getClassLoader();
public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { ... }
public final String getString(@StringRes int resId) { ... }
public final int getColor(@ColorRes int id) { ... }
public final Drawable getDrawable(@DrawableRes int id) { ... }
public abstract Resources.Theme getTheme();
public abstract void setTheme(@StyleRes int resid);
public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { ... }
// 3,获取应用相关信息
public abstract ApplicationInfo getApplicationInfo();
public abstract String getPackageName();
public abstract Looper getMainLooper();
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
// 4,获取缓存文件
public abstract File getSharedPreferencesPath(String name);
public abstract File getDataDir();
public abstract boolean deleteFile(String name);
public abstract File getExternalFilesDir(@Nullable String type);
public abstract File getCacheDir();
...
public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);
public abstract boolean deleteSharedPreferences(String name);
// 5,数据库相关
public abstract SQLiteDatabase openOrCreateDatabase(...);
public abstract boolean deleteDatabase(String name);
public abstract File getDatabasePath(String name);
...
// 其它,如监听配置信息改变、内存不足等
public void registerComponentCallbacks(ComponentCallbacks callback) { ... }
public void unregisterComponentCallbacks(ComponentCallbacks callback) { ... }
...
}
public interface ComponentCallbacks {
void onConfigurationChanged(Configuration newConfig);
void onLowMemory();
}
ContextWrapper源码:这是一个装饰类,这儿运用到了装饰者模式,ContextWrapper和它的子类都是装饰者,ContextImpl是被装饰者。
public class ContextWrapper extends Context {
//竟然只有这一个成员,看来是相当重要了,记住mBase,mBase,mBase,重要的事儿说三遍
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
//重要:注意这个方法,ContextWrapper就是通过这个方法将ContextImpl对象赋值给mBase成员变量的
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
//得到的是mBase
public Context getBaseContext() {
return mBase;
}
//看,下面的方法都是通过mBase来执行的,所以这是个代理类
@Override
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();
}
//常常用的方法,getApplicationContext方法是在ContextWrapper类实现的,但最终是在ContextImpl实现的
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
@Override
public Resources.Theme getTheme() {
return mBase.getTheme();
}
@Override
public ClassLoader getClassLoader() {
return mBase.getClassLoader();
}
@Override
public String getPackageName() {
return mBase.getPackageName();
}
@Override
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
}
@Override
public String getPackageCodePath() {
return mBase.getPackageCodePath();
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return mBase.getSharedPreferences(name, mode);
}
...
}
ContextThemeWrapper源码:可以看出,相比ContextWrapper,虽然都是Context的代理类,但ContextThemeWrapper有自己的Resource和Theme成员,并且可以通过构造函数初始化自己的Resource和Theme,也就是说,ContextThemeWrapper和它的mBase成员在Resource和Theme相关的行为上是不同的。
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, @StyleRes int themeResId) {
super(base);
mThemeResource = themeResId;
}
public ContextThemeWrapper(Context base, Resources.Theme theme) {
super(base);
mTheme = theme;
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
if (mResources != null) {
throw new IllegalStateException(
"getResources() or getAssets() has already been called");
}
if (mOverrideConfiguration != null) {
throw new IllegalStateException("Override configuration has already been set");
}
mOverrideConfiguration = new Configuration(overrideConfiguration);
}
public Configuration getOverrideConfiguration() {
return mOverrideConfiguration;
}
@Override
public AssetManager getAssets() {
// Ensure we're returning assets with the correct configuration.
return getResourcesInternal().getAssets();
}
@Override
public Resources getResources() {
return getResourcesInternal();
}
private Resources getResourcesInternal() {
if (mResources == null) {
if (mOverrideConfiguration == null) {
mResources = super.getResources();
} else {
final Context resContext = createConfigurationContext(mOverrideConfiguration);
mResources = resContext.getResources();
}
}
return mResources;
}
@Override
public void setTheme(int resid) {
if (mThemeResource != resid) {
mThemeResource = resid;
initializeTheme();
}
}
@Override
public int getThemeResId() {
return mThemeResource;
}
@Override
public Resources.Theme getTheme() {
if (mTheme != null) {
return mTheme;
}
mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getApplicationInfo().targetSdkVersion);
initializeTheme();
return mTheme;
}
@Override
public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
}
return mInflater;
}
return getBaseContext().getSystemService(name);
}
protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {
theme.applyStyle(resId, true);
}
private void initializeTheme() {
final boolean first = mTheme == null;
if (first) {
mTheme = getResources().newTheme();
final Resources.Theme theme = getBaseContext().getTheme();
if (theme != null) {
mTheme.setTo(theme);
}
}
onApplyThemeResource(mTheme, mThemeResource, first);
}
}
ContextImpl源码:这是Context的主要实现类,可以用于创建Activity、Service和Application的mBase成员,即ContextWrapper和ContextThemeWrapper代理的是ContextImpl对象本身;
而且ContextImpl相比ContextThemeWrapper没有Configuration对象,在ContextThemeWrapper类中,Resource是根据Configuration对象初始化的;
还可以看出Service和Application使用同一个Resource,和Activity使用的不同。
class ContextImpl extends Context {
//整个App的主线程
final ActivityThread mMainThread;
//整个App的相关信息
final LoadedApk mPackageInfo;
//资源解析器
private final ResourcesManager mResourcesManager;
//App资源类
private final Resources mResources;
//外部Context的引用
private Context mOuterContext;
//默认主题
private int mThemeResource = 0;
private Resources.Theme mTheme = null;
//包管理器
private PackageManager mPackageManager;
// 用于创建 Activity Context
static ContextImpl createActivityContext(...) {
ContextImpl context = new ContextImpl(...);
context.setResources(resourcesManager.createBaseActivityResources(...));
return context;
}
// 用于创建 Application Context、Service Context
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
ContextImpl context = new ContextImpl(...);
context.setResources(packageInfo.getResources());
return context;
}
private static Resources createResources(...) {
return ResourcesManager.getInstance().getResources(...);
}
//启动Activity的地方
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
//看,特熟悉的getApplicationContext,最终就是在这儿实现的,不管是哪个方法,最后都是返回的都是当前应用的Application对象
//另外Activity类中的getApplication()方法返回的也是当前应用的Application对象,只是返回值类型不同而已
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
// ContextThemeWrapper 没有重写父类的 setResources
// 因此会调用 mBase 的 setResources,即和 ContextImpl 的行为一样
void setResources(Resources r) {
if (r instanceof CompatResources) {
((CompatResources) r).setContext(this);
}
mResources = r;
}
@Override
public Resources getResources() {
return mResources;
}
/* ---------- 主题相关 ------------ */
@Override
public void setTheme(int resId) {
synchronized (mSync) {
if (mThemeResource != resId) {
mThemeResource = resId;
initializeTheme();
}
}
}
// 直接创建一个 Themem 对象,相比 ContextThemeWrapper,少了一部分内容
private void initializeTheme() {
if (mTheme == null) {
mTheme = mResources.newTheme();
}
mTheme.applyStyle(mThemeResource, true);
}
@Override
public Resources.Theme getTheme() {
synchronized (mSync) {
// 和 ContextThemeWrapper 基本一样
if (mTheme != null) {
return mTheme;
}
mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getOuterContext().getApplicationInfo().targetSdkVersion);
initializeTheme();
return mTheme;
}
}
}
未完待续。。