1 事件感知
绝大多数情况下,View 是不需要感知外部组件的生命周期或系统事件的。但部分情况下,View 对外部事件的感知又是必要的,比如广告轮播组件:Banner,这样的控件在设计之初就要考虑亮屏、息屏、Activity 的 onResume 和 onPause 生命周期,因为谁也不希望 Banner 在这些节点处继续执行轮播操作。
如果将 Banner 当成一个 ItemView 放入 Listiew、RecyclerView 等具有复用机制的容器中时,新的问题又出现了,当 Banner 被滑出屏幕,又重新滑回屏幕后,之前的轮播状态是无法保持的。所以,我们需要知道 Banner 被销毁和重建的窗口,在销毁时记录轮播状态,在重建时将轮播状态复位。这样,用户就会有一致的轮播状态体验了。
下面将会结合以上需求对每种事件和生命周期的感知进行详细的阐述。案例项目会托管在 Github 上,如需查看,请点击 Receptor@Github。
1.1 onAttachedToWindow 与 onDetachedFromWindow
这两个方法是 View 自身的方法。当 View 被添加到窗体中时,onAttachedToWindow 会被调用,此时它有一个 Surface 并将开始绘制,非严格意义上说,这时用户已经可以看到你的 View 了,因为系统渲染 View 的速度非常快。当 View 从窗体中被移除时,onDetachedFromWindow 会被调用,此时它不再拥有用于绘制的 Surface,这时用户的直观感受是看不到你的 View 了。
View 被添加到窗体和从窗体中被移除的监听很好实现,只需要继承父 View 重写 onAttachedToWindow 和 onDetachedFromWindow,然后增加自己的监听逻辑即可。实现方式大概像这样:
1 | public class CustomView extends FrameLayout { |
1.2 BroadcastReceiver
onAttachedToWindow 和 onDetachedFromWindow 已经能够实现 View 自身被添加或移除的监听了,但是,我们还想监听亮屏、息屏等系统事件。在 Android 中,这些系统事件是通过广播的方式来告知感兴趣的组件的。所以,我们需要在 View 的生命周期中注册一个广播接收者,来完成系统事件的监听。onAttachedToWindow 和 onDetachedFromWindow 刚好可以成为广播注册、反注册的窗口,实现方式大概像这样:
1 | public class CustomView extends FrameLayout { |
1.3 Lifecycle
Lifecycle 是 Android 推出的一个生命周期管理组件,通过观察者模式对 Activity 或 Fragment 进行生命周期的感知。Lifecycle 组件包括 LifecycleOwner 和 LifecycleObserver,LifecycleOwner 是生命周期的持有者,负责提供生命周期事件;LifecycleObserver 是生命周期的观察者,负责感知生命周期事件,做出相应动作。
Android 系统的 Activity 和 Fragment 均实现了 LifecycleOwner 接口,使得这两个组件成为了生命周期事件的提供者。这时如果在 Activity 或 Fragment 中添加 Observer(生命周期的观察者),它们父类中的 LifecycleRegistry 类会将 [ Activity、 Fragment – 事件提供者] 和 [ LifecycleObserver – 事件观察者] 关联到一起,这样 LifecycleObserver 就会感知到 LifecycleOwner 生命周期的变化。
如果我们的自定义 View 也想感知到 Activity、Fragment 的生命周期,该怎么办呢?只需要让 View 实现 DefaultLifecycleObserver 接口,使得 View 成为观察者,然后将其与 LifecycleOwner 关联即可。实现方式如下:
注意:如果想使用 DefaultLifecycleObserver 接口,minSdkVersion 需要大于等于 24,否则会报错。
1.3.1 添加引用
在 Module 的 build.gradle 文件中的 dependencies 节点增加引用,如果 Android Studio 使用 JDK8,需要引入 Java8 的库。
1 | dependencies { |
1.3.2 实现接口
笔者的测试项目中使用了 JDK8,并且 minSdkVersion=24,所以这里的自定义 View 直接实现了 DefaultLifecycleObserver 接口并实现了全部方法。
1 | import android.arch.lifecycle.DefaultLifecycleObserver; |
1.3.3 布局引用
1 |
|
1.3.4 关联组件
组件关联的时候,需要创建 DefaultLifecycleObserver 的实例,本例中是实现类 CustomView 的实例,然后将其添加到 Observer 中,就可以进行生命周期的感知了。
1 | package com.sunzn.receptor; |
1.3.5 测试结果
1 | 2018-11-08 09:45:45.241 13036-13036/com.sunzn.receptor D/CustomView: onCreate |