1.1.1. Context
1.Context子类结构
Context是一个抽象基类,Context下有两个子类。
- ContextWrapper是上下文功能的封装类
- ContextImpl则是上下文功能的实现类
ContextWrapper又有三个直接的子类
- ContextThemeWrapper
- Service
- Application
其中,ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity,所以Activity和Service以及Application的Context是不一样的,只有Activity需要主题,Service不需要主题。
在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的。
不过有几种场景比较特殊,比如启动Activity,还有弹出Dialog。出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则将会出错。
2.Context数量
Context数量 = Activity数量 + Service数量 + Application
3.getApplicationContext()和getApplication()区别
getApplication()只存在于Activity和Service对象; 那么对于BroadcastReceiver和ContentProvider却无法获取Application, 这时就需要一个能在Context上下文直接使用的方法, 那便是getApplicationContext().
两者对比:
- 对于Activity/Service来说, getApplication()和getApplicationContext()的返回值完全相同; 修改过接口;
- BroadcastReceiver在onReceive的过程, 能使用getBaseContext().getApplicationContext获取所在Application, 而无法使用getApplication;
- ContentProvider能使用getContext().getApplicationContext()获取所在Application. 绝大多数情况下没有问题, 但是有可能会出现空指针的问题, 情况如下:
当同一个进程有多个apk的情况下, 对于第二个apk是由provider方式拉起的, 前面介绍过provider创建过程并不会初始化所在application, 此时执行 getContext().getApplicationContext()返回的结果便是NULL. 所以对于这种情况要做好判空.
Tips: 如果对于Application理解不够深刻, 建议getApplicationContext()方法谨慎使用, 做好是否为空的判定,防止出现空指针异常.
4.Application作用:
- 保存应用进程内的全局变量
- 初始化操作
- 提供应用上下文
Application生命周期
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
}
frameworks/base/core/java/android/app/Instrumentation.java
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
/* package */ final void attach(Context context) {
attachBaseContext(context); // 设置上下文
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
- 构造函数
- attachbaseContext
- onCreate