从视图中获取当前活动,片段,生命周期所有者的简单方法



当编写Views时,ViewModelsLiveData生命周期感知的。ViewModel想要的是当前FragmentActivityLiveData当前LifecycleOwner。您事先不知道您的视图是否会被包装或有些。因此,它需要一个灵活的函数来查找所需的上下文。我最终得到了这两种方法:

private FragmentActivity getFragmentActivity() {
    Context context = getContext();
    while (!(context instanceof FragmentActivity)) {
        context = ((ContextWrapper) context).getBaseContext();
    }
    return (FragmentActivity) context;
}
private LifecycleOwner getLifecycleOwner() {
    Context context = getContext();
    while (!(context instanceof LifecycleOwner)) {
        context = ((ContextWrapper) context).getBaseContext();
    }
    return (LifecycleOwner) context;
}

现在,这是要放入每个视图的大量样板代码。有没有更简单的方法?

我不想为此使用自定义的 View 基类,因为大型层次结构很丑陋。另一方面,组合需要与此解决方案一样多的代码。

你可以找到它 lifecycle-runtime-ktx

fun View.findViewTreeLifecycleOwner(): LifecycleOwner? = ViewTreeLifecycleOwner.get(this)

Kotlin 扩展

fun Context.fragmentActivity(): FragmentActivity? {
    var curContext = this
    var maxDepth = 20
    while (--maxDepth > 0 && curContext !is FragmentActivity) {
        curContext = (curContext as ContextWrapper).baseContext
    }
    return if(curContext is FragmentActivity)
        curContext
    else
        null
}
fun Context.lifecycleOwner(): LifecycleOwner? {
    var curContext = this
    var maxDepth = 20
    while (maxDepth-- > 0 && curContext !is LifecycleOwner) {
        curContext = (curContext as ContextWrapper).baseContext
    }
    return if (curContext is LifecycleOwner) {
        curContext as LifecycleOwner
    } else {
        null
    }
}

用法

val lifecycleOwner = context.lifecycleOwner()
val fragmentActivity = context.fragmentActivity()

类似于另一个答案,但不需要指定 maxDepth:

 val Context.lifecycleOwner: LifecycleOwner?
    get() {
        var context: Context? = this
        while (context != null && context !is LifecycleOwner) {
            val baseContext = (context as? ContextWrapper?)?.baseContext
            context = if (baseContext == context) null else baseContext
        }
        return if (context is LifecycleOwner) context else null
    }

如果你不想使用组合,你可以把它放到公共的BaseView类中。 或者,您可以在某些 utils 类中使其成为静态方法。

如果你使用 Kotlin,你也可以让它成为 Kotlin 扩展函数,我最喜欢的方式是什么。

最新更新