【问题标题】:Kotlin Recursive Extension Function to Walk Android View Hierarchy遍历 Android 视图层次结构的 Kotlin 递归扩展函数
【发布时间】:2018-02-15 16:34:06
【问题描述】:

我正在尝试创建一个通用扩展函数,它可以遍历 Android 视图层次结构并返回特定类型视图的第一次出现。

我们的想法是按如下方式调用扩展(在parentView 中查找Toolbar 的第一次出现):

val someView = parentView.findFirstChildRecursive<Toolbar>()

很遗憾,下面的代码无法编译。我猜 Kotlin 对递归内联函数不满意,但是如果不内联函数,我就不能使用具体类型。

inline fun <reified T> View.findFirstChildRecursive(): T? {
  when (this) {
    is T -> return this
    is ViewGroup -> {
      for (i in 0 until childCount) {
        getChildAt(i).findFirstChildRecursive<T>()?.let { return it }
      }
    }
  }
  return null
}

我是一个 Kotlin 新手,所以我希望有人能解释原因或提出一个好的解决方案?

【问题讨论】:

  • 提供的答案有帮助吗?
  • @VictorRendina 你有没有找到解决方案?我也在尝试做同样的事情。
  • @portfoliobuilder 请在下面查看我的答案,了解一种潜在的解决方案

标签: android kotlin kotlin-extension


【解决方案1】:

我将在 Victor Rendina 的回答中添加一点内容。

你可以有两个函数:一个带有clazz: Class&lt;T&gt;参数,另一个带有reified generic:

inline fun <reified T : View> View.findFirstChildRecursive(): T? {
    return findFirstChildRecursive(T::class.java)
}

fun <T: View> View.findFirstChildRecursive(clazz: Class<T>): T? {
    if (this::class.java == clazz) {
        @Suppress("UNCHECKED_CAST")
        return this as T
    } else if (this is ViewGroup) {
        for (i in 0 until childCount) {
            getChildAt(i).findFirstChildRecursive(clazz)?.let { return it }
        }
    }
    return null
}

【讨论】:

    【解决方案2】:

    基本上,Kotlin 不允许您内联递归函数,因为它可能不得不内联无限数量的调用。

    查看此相关帖子: Can a recursive function be inline?

    上面的方法也不能是tailrec函数,因为调用自身并不是函数中的最后一个操作。

    在此处查看 Kotlin 函数文档: https://kotlinlang.org/docs/reference/functions.html

    如果你仍然想实现类似的东西,你可以将类传递给函数。

    val someView = parentView.findFirstChildRecursive(Toolbar::class.java)

    fun <T: View> View.findFirstChildRecursive(clazz: Class<T>): T? {
        if (this::class.java == clazz) {
            @Suppress("UNCHECKED_CAST")
            return this as T
        } else if (this is ViewGroup) {
            for (i in 0 until childCount) {
                getChildAt(i).findFirstChildRecursive(clazz)?.let { return it }
            }
        }
        return null
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-07
      • 1970-01-01
      • 2012-04-21
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多