【问题标题】:Using Generics to find fragment in childFragmentManager using "is" not useable?使用泛型在 childFragmentManager 中使用“is”查找片段不可用?
【发布时间】:2018-06-02 04:13:50
【问题描述】:

我正在尝试在旋转时恢复 ViewPager 中的片段以解决一些问题,并编写了一些正常使用时可以完美运行的代码,但是当我尝试使其成为通用函数以重用它时,它不起作用。

无论我尝试使用传入的参数在childFragmentManager.fragments.find lambda 中执行的操作,在尝试执行 IS 检查时仍然是红色且无法使用。

工作代码

val studySurveyFragment = if (restoring) {
            val fragment = childFragmentManager.fragments.find { it is StudySurveyFragment }
            if (fragment == null) {
                StudySurveyFragment()
            } else {
                fragment as StudySurveyFragment
            }
        } else {
            StudySurveyFragment()
        }

我对通用版本的尝试

create(StudySurveyFragment(), StudySurveyFragment::class.java)

fun <T> create(fragment: Fragment, fragmentClass: Class<T>): Fragment {
        return if (restoring) {
            val findFragment = childFragmentManager.fragments.find { it is fragmentClass }
            if (findFragment == null) {
                fragment
            } else {
                findFragment
            }
        } else {
            fragment
        }
    }

更新:我也试过这样做,它会编译,但检查实际上不起作用

childFragmentManager.fragments.find {it.javaClass.isInstance(fragmentClass)}

注意:我知道可以使用一些 elvis 操作符来减少这种情况,但我试图首先让它按预期工作......

【问题讨论】:

  • 我认为您不应该调用片段。那不是受限制的 API 吗?
  • 您的 is-check 错误。你是在问这个类是否是一个类,而不是一个东西。考虑改用内联具体化函数,然后您甚至不需要传递类引用。
  • 你建议的工作,但我仍然必须通过类引用才能在其他地方实例化它?如果你为它写一个答案,我可以标记它。 inline fun FragmentManager.findOrCreateFragment(clazz: Class): T? { return this.fragments.find { 它是 T } 作为 T? ?: clazz.newInstance() }
  • API 也不受限制,只是我调用子片段管理器。我需要相同的片段来重新附加我的演示者,否则它是空的。
  • 也刚刚意识到我不需要返回 T?可以返回T

标签: android generics kotlin


【解决方案1】:

你正在寻找的是这样的:

inline fun <reified T : Fragment> FragmentManager.findOrCreateFragment(): T {
    return fragments.find { it is T } as T? ?: T::class.java.newInstance()
}

无需传递类引用。

PS:我很确定 fragmentManager.getFragments()(或者,在 Kotlin 中,fragmentManager.fragments曾经是受限的 API,但你是对的,它似乎没有不再这样了。

【讨论】:

  • 不应该findOrCreate 返回一个非空值吗?当find 方法返回 null 时,我们都会创建一个新实例。
  • 是的,当然。我只是漫不经心地保留了你原来的方法签名。
  • 哦,同样值得注意的是,您可以使用安全转换运算符as?
  • 天哪!你摆脱了像我想的那样通过课程的需要。!感谢您进一步清理它并让我知道我做错了什么。
【解决方案2】:

看起来我可以在没有泛型的情况下做到这一点......但经过进一步考虑,使用泛型我可以去 clazz.newInstance() 而不必创建类来检查会更有效,所以如果有办法这样做我更喜欢它。

fun create(fragment: Fragment): Fragment {
        return if (restoring) {
            val findFragment =
                childFragmentManager.fragments.find { it.javaClass.isInstance(fragment) }
            if (findFragment == null) {
                fragment
            } else {
                findFragment
            }
        } else {
            fragment
        }
    }

可以缩短到这个,也意识到如果它不恢复,它们无论如何都会为空......

fun findOrCreate(fragment: Fragment): Fragment {
     return childFragmentManager.fragments.find { it.javaClass.isInstance(fragment) } ?: fragment
}

【讨论】:

    猜你喜欢
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 2016-11-11
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多