【Android面试-Android-V07】Context

19 阅读2分钟

Context

image

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().

两者对比:
  1. 对于Activity/Service来说, getApplication()和getApplicationContext()的返回值完全相同; 修改过接口;
  2. BroadcastReceiver在onReceive的过程, 能使用getBaseContext().getApplicationContext获取所在Application, 而无法使用getApplication;
  3. 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