1. 什么是 context?

作为安卓开发工程师,Context是咱们常常运用的一个重要概念。

从代码的角度来看,Context是一个笼统类,它代表着应用程序环境和运行时状况的信息。Context具有许多子类,包括Activity和Service等,每个子类都代表着不同的应用程序环境和状况。

从规划的角度来看,Context是一个非常重要的概念,由于它答应咱们在应用程序中拜访体系资源,例如数据库,同享偏好设置和体系服务等。Context还答应咱们在应用程序中创立新的组件,例如Activity和Service等。

实际上,Context在安卓开发中简直无处不在。例如,咱们能够运用Context来发动一个新的Activity,获取应用程序的资源,读取和写入文件,以及拜访体系服务和传感器等。Context还能够协助咱们办理应用程序的生命周期,例如在应用程序销毁时开释资源。

总归,Context是安卓开发中不可或缺的概念,它答应咱们拜访体系资源,办理应用程序的生命周期,并与体系交互。了解Context的概念和运用办法关于成为一名优秀的安卓开发工程师至关重要。

2. context承继联系

Context
├── ContextImpl
├── ContextWrapper
│   ├── Application
│   ├── Service
│   ├── ContextThemeWrapper
│   │   ├── Activity
│   │   │   ├── FragmentActivity
│   │   │   └── ...
│   │   └── ...
│   └── ...
└── ...

Context是一个笼统类,它有多个直接或间接的子类。

ContextImpl是Context的一个完结类,真正完结了Context中的一切函数,所调用的各种Context类的办法,其完结均来自于该类。

ContextWrapper是一个包装类,它能够包装另一个Context目标,并在其基础上添加新的功用。内部包括一个真正的Context引用,调用ContextWrapper的办法都会被转向其所包括的真正的Context目标。

ContextThemeWrapper是一个特别的包装类,它能够为应用程序的UI组件添加主题款式。主题便是指Activity元素指定的主题。只要Activity需求主题,所以Activity承继自ContextThemeWrapper,而Application和Service直接承继自ContextWrapper。

总归,Context的承继联系非常杂乱,但是了解这些联系关于在安卓开发中正确地运用Context非常重要。经过承继联系,咱们能够了解每个Context子类的效果和用处,而且能够选择合适的Context目标来拜访应用程序的资源和体系服务。

3.Context怎么创立

在安卓应用程序中,Activity是经过调用startActivity()办法来发动的。当咱们发动一个Activity时,体系会经过调用Activity的生命周期办法来创立、发动和销毁Activity目标。
而其间创立Activity的办法最终是走到ActivityThread.performLaunchActivity()办法。将其间无关办法删除后:
、、、
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

//创立 ContextImpl目标
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;

    //创立Activity目标
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    ...
    //Activity初始化
    activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, title, r.parent,
            r.embeddedID, r.lastNonConfigurationInstances, config,
            r.referrer, r.voiceInteractor, window, r.configCallback,
            r.assistToken, r.shareableActivityToken);
    //Theme设置
    int theme = r.activityInfo.getThemeResource();
    if (theme != 0) {
        activity.setTheme(theme);
    }
    return activity;
}

、、、
能够看到Activity的创立过程非常清楚:

  1. 创立ContextImpl目标,办法最终走到静态办法ContextImpl.createActivityContext()创立。
  2. 创立Activity目标,最终instantiateActivity()经过调用Class的newInstance()办法,反射创立出来,办法注解到This method is only intended to provide a hook for instantiation. It does not provide earlier access to the Activity object. The returned object will not be initialized as a Context yet and should not be used to interact with other android APIs.,办法只创立了Activity的前期目标,并没有对它做Context的初始化,所以不能调用安卓相关api。简略来说,Activity自身承继自ContextWrapper,这个办法并没有详细完结任何Context的办法,只是将一切办法代理给了内部的baseContext,所以反射创立后,调用任何的体系的办法都是无效的。
  3. Activity初始化,调用Activity.attch(),这个办法对Activity做各种所需的初始化,Context、Thread、parent、Window、Token等等,而Context的初始化便是调用ContextWrapper.attachBaseContext()把第一步创立的ContextImpl设置到baseContext。
  4. Theme设置,前面说到Activity完结的是ContextThemeWrapper,对ContextWrapper扩展并支撑了Theme的替换,调用ContextThemeWrapper.setTheme()完结Theme的初始化。

4.一些考虑

  1. ContextThemeWrapper作为ContextWrapper一个扩展,它是重写了ContextImpl中的一些关于Theme的完结,也便是说ContextImpl自身也是有Theme的完结,它供给的Theme是整个APP的Theme,而这里扩展了之后,支撑了Theme的替换之后,在不同的页面支撑了不同的Theme设置。

  2. Context作为应用程序环境和运行时状况的信息,规划初衷上它应该是固定的,在创立成功之后就制止改动,所以在ContextWrapper.attachBaseContext()中设置了拦截,只答应设置一次baseContext,从头设置会抛出反常。但是在一些特别的场景中,比方跨页面运用View,或者提早创立View的时候,其实会有场景涉及替换Context。另一个坑是ContextWrapper约束baseContext只答应体系调用。不过在SDK31中,官方供给了一个特别版别的ContextWrapper,也便是MutableContextWrapper,支撑了替换baseContext。

  3. Context规划是很典型的装修器形式,Context笼统界说了详细的接口;ContextImpl详细完结了Context界说的一切办法;ContextWrapper承继了Context接口,并包装了详细完结ContextImpl;ContextThemeWrapper承继了ContextWrapper并扩展了替换Theme的功用。

5. 附录

装修器形式是一种结构型规划形式,它答应咱们在运行时动态地为一个目标添加新的行为,而无需修正其源代码。装修器形式经过将目标包装在一个装修器目标中,来添加目标的功用。装修器形式是一种非常灵活的形式,它能够在不改动原始目标的情况下,动态地添加新的行为和功用。

装修器形式的中心思维是将目标包装在一个或多个装修器目标中,这些装修器目标具有与原始目标相同的接口,能够在不改动原始目标的情况下,为其添加新的行为。装修器目标能够嵌套在一起,形成一个链式结构,从而完结更杂乱的功用。

装修器形式的结构由四个基本元素组成:

  1. 笼统组件(Component):界说了一个目标的基本接口,能够是一个笼统类或接口。

  2. 详细组件(ConcreteComponent):完结了笼统组件接口,是被装修的目标。

  3. 笼统装修器(Decorator):承继或完结了笼统组件接口,用于包装详细组件或其他装修器。

  4. 详细装修器(ConcreteDecorator):承继或完结了笼统装修器接口,完结了详细的装修逻辑。

装修器形式的长处在于:

  1. 能够动态地为目标添加新的行为,无需修正其源代码。

  2. 能够嵌套多个装修器目标,形成一个链式结构,从而完结更杂乱的功用。

  3. 装修器目标与原始目标具有相同的接口,能够彻底代替原始目标。

装修器形式的缺陷在于:

  1. 或许会导致类的数量添加,添加代码的杂乱度。

  2. 在装修器链中,有些装修器或许不被运用,但仍然需求创立和维护,浪费资源。