Android - Context

Android - Context_第1张图片

一、概念 

        Context 是应用程序和系统之间的桥梁,用于获取全局消息、访问系统资源、调用应用程序级的操作。一般直接调用 Context 的方法或者调用接口时传入Context。
        Android应用模型是基于组件的应用设计模式,组件的运行要有一个完整的Android工程环境。一个Android程序可以理解为一部电影,四大组件(Activity、Service、BroadcastReceiver、ContentProvider)就好比戏里的四个主角,它们是剧组(系统)一开始定好的,主角并不是大街上随便拉个人(new 一个对象)都能演的。有了演员当然也得有摄像机拍摄,它们必须通过镜头(Context)才能将戏传给观众,这也就正对应说四大组件必须工作在Context环境下。那么Button、TextView等等控件就相当于群演,显然没那么重要随便一个路人甲都能演(可以new一个对象),但是它们也必须在面对镜头(工作在Context环境下),所以Button mButtom = new Button(context) 是可以的。
ContextImpl 是 Context 接口的真正实现者,我们调用的各种 Context 方法均来自于该类的实现。然后赋值给ContextWrapper。
ContextWrapper 是一个装饰类,构造中需要传入一个真正的 Context 引用,提供了 attachBaseContext() 用于指定真正的 Context 实现对象。所以虽然 Activity、Service、Application 都继承自 ContextWrapper 但初始化过程中都会创建 ContextImpl 对象由它实现 Context 接口中的方法。
ContextThemeWrapper 内部包含了与主题 Theme 相关的接口,就是在 AndroidManifest 中通过 android:theme 指定的主题,只有 Activity 才需要主题。
Application 特点是生命周期长,在整个应用程序运行的期间他都会存在。同时我们可以自定义Application,并在onCreate()里面做一些全局的初始化操作。在不涉及UI以及启动Activity操作时使用
Activity 是一个拥有主题的 Context 对象。Activity常用于与UI有关的操作,如添加window等。常规使用可以直接用 activity.this。
Service 也可以和Activity一样直接使用 service.this 来使用 Context。

Broadcast

ContextProvider

所持有的 Context 是外部传入的。

二、选择

        一般 Context 造成的内存泄漏,几乎都是当 Context 销毁的时候却因为被引用导致销毁失败。

        出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个 Activity 的启动必须要建立在另一个 Activity 的基础之上,也就是以此形成返回栈,所以在非 Activity 环境下启动 Activity 需要 Intent 指定 FLAG_ACTIVITY_NEW_TASK 这个 Flag。而Dialog则必须在一个 Activity 上面弹出(除非是System Alert类型的Dialog),因此在这种场景下只能使用 Activity 类型的Context 否则报错。

        在 Application 和 Service 中去 Layout Inflate 也是合法的,但会使用系统默认的主题样式,如果自定义了某些样式可能不会被使用,因此不推荐。

  • 当 Application 的 Context 能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。
  • 凡是跟 UI 相关的都应该使用 Activity 作为 Context 来处理。
  • 不要让生命周期长于 Activity 的对象持有到 Activity 的引用。
  • 尽量不要在 Activity 中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。
Application Activity Service
弹出Dialog No Yes No
启动Activity 不推荐 Yes 不推荐
启动Service Yes Yes Yes
发送和注册Broadcast Yes Yes Yes
加载Layout 不推荐 Yes 不推荐
加载Resource Yes Yes Yes

三、获取

View.getContext( ) 返回当前 View 的 Context 对象,通常是当前正在展示的 Activity 对象。
Activity.getApplicationContext( ) 获取当前 Activity 所在进程的 Context 对象,通常使用 Context 对象时优先考虑这个全局的进程Context。
ContextWrapper.getBaseContext( ) 用来获取一个 ContextWrapper 进行装饰之前的 Context,实际开发中使用的不多,也不建议使用。
Activity.this 返回当前 Activity 实例,跟 UI 相关的都应该使用 Activity 作为 Context 避免内存泄漏。

四、面试相关

4.1 一个应用程序有几个Context?

应用程序中 Context 的子类是 Activity、Service、Application(注意 Broadcast 和 ContextProvider 持有的 Context 都是外部传入的因此不算),所以 Comtext 数量 = Activity数量 + Service数量 + 1。

4.2 getApplication() 和 getApplicationContext() 区别?

获得的对象相同,作用域不同(语义的区别,getApplication() 只在 Activity 和 Service 中有,在别的地方获取例如 BroadcastReceiver 中就要使用 getApplicationContext() 了)。

你可能感兴趣的:(Android,android)