android - 如何让自定义视图观察包含片段的生命周期事件而不是活动?
问题描述
我有一个活动和几个片段,它在框架布局中替换。每个片段都包含一个从 XML 扩展而来的布局,其中包含许多自定义视图。在这些视图中,我想使用 LifecycleObserver 订阅这些视图中的生命周期事件。我对 Kotlin 的看法:
class MyView(context: Context) : View(context, null, 0): LifecycleObserver {
init {
(getContext() as LifecycleOwner).lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
// code
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
// code
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
lifecycle.removeObserver(this)
}
}
问题是,当一个片段消失并被另一个片段替换时,第一个片段中的视图不会收到onPause事件。当我从第二个片段返回到它时,他们也没有得到onResume 。只有在整个活动暂停时,视图才会收到onPause,但它们不知道片段中的生命周期变化。我将此追踪到布局充气器,用于充气片段的 xml 布局,它将活动作为上下文参数传递给视图。这是布局充气器在支持库的 Fragment 类中实例化的方式:
/** @deprecated */
@Deprecated
@NonNull
@RestrictTo({Scope.LIBRARY_GROUP})
public LayoutInflater getLayoutInflater(@Nullable Bundle savedFragmentState) {
if (this.mHost == null) {
throw new IllegalStateException("onGetLayoutInflater() cannot be executed until the Fragment is attached to the FragmentManager.");
} else {
LayoutInflater result = this.mHost.onGetLayoutInflater();
this.getChildFragmentManager();
LayoutInflaterCompat.setFactory2(result, this.mChildFragmentManager.getLayoutInflaterFactory());
return result;
}
}
mHost是一个 FragmentActivity 包含这个片段。因此,传递到片段的 onCreateView() 的 LayoutInflater 包含对 FragmentActivity 的引用作为上下文。因此视图有效地观察了 Activity 生命周期。
如何让我的自定义视图观察其包含片段的生命周期事件?
解决方案
如果您只使用onPause()
and onResume()
,在您的 View 类中覆盖onDetachedFromWindow()
andonAttachedToWindow()
就足够了:
override fun onAttachedToWindow() {
//onResume code
}
override fun onDetachedFromWindow() {
//onPause code
}
您还可以创建自己的生命周期方法:
fun onResume() {}
fun onPause() {}
从您的片段中,您可以保留对您的视图的全局引用:
//`by lazy` only initializes the variable when it's fist called,
//and then that instance is used for subsequent calls.
//Make sure you only reference `myView` after `onCreateView()` returns
private val myView by lazy { view.findViewById<MyView>(R.id.my_view) }
然后从您的 Fragment 的onPause()
andonResume()
中,调用您的 View 的相应方法:
override fun onPause() {
myView.onPause()
}
override fun onResume() {
myView.onResume()
}
编辑:
为了可扩展性,制作您自己的 min-SDK。创建一个基本的 Fragment 类:
open class LifecycleFragment : Fragment() {
internal fun dispatchOnResume(parent: View) {
if (parent is CustomLifecycleObserver) parent.onResume()
if (parent is ViewGroup) {
for (i in 0 until parent.childCount) {
dispatchOnResume(parent.getChildAt(i))
}
}
}
internal fun dispatchOnPause(parent: View) {
if (parent is CustomLifecycleObserver) parent.onPause()
if (parent is ViewGroup) {
for (i in 0 until parent.childCount) {
dispatchOnResume(parent.getChildAt(i))
}
}
}
override fun onResume() {
dispatchOnResume(view)
}
override fun onPause() {
dispatchOnPause(view)
}
}
(CustomLifecycleListener
将是您的视图实现、包含onResume()
和onPause()
方法的接口。)
然后只需在您的其他片段中扩展该类:
class SomeFragment : LifecycleFragment() {}
推荐阅读
- c# - 使用 C# DataContract 将 JSON 的一部分反序列化为字典
- javascript - 未捕获的语法错误:尝试解析 JSON 时 JSON 中位置 0 处出现意外标记 l
- opencv - 如何通过环境变量将 OpenCL 设备设置为 Intel
- multidimensional-array - 从两个不同数组的值计数创建 Array2D
- sql - 如何从具有相同列路径的另一个表中填充一个表
- apache-spark - 如何在 Spark SQL 查询中转义特殊字符,“`”似乎不起作用
- php - 无法在 AWS Elastic Beanstalk 实例中部署新版本
- python - 没有 multiprocessing.cpu_count?
- google-analytics - 在谷歌分析中,为什么我在 abc.com 帐户下看到 xyz.com 页面访问?
- java - 为什么我的登录表单与空密码字段连接?