Kotlin递归扩展函数遍历Android视图层次结构
我正在尝试创建一个通用扩展函数,它可以遍历Android视图层次结构并返回特定类型视图的第一次出现 其想法是按如下方式调用扩展以查找parentView中第一个出现的工具栏: 不幸的是,下面的代码没有编译。我想Kotlin不喜欢使用递归内联函数,但我不能在不内联函数的情况下使用具体化类型Kotlin递归扩展函数遍历Android视图层次结构,android,kotlin,kotlin-extension,Android,Kotlin,Kotlin Extension,我正在尝试创建一个通用扩展函数,它可以遍历Android视图层次结构并返回特定类型视图的第一次出现 其想法是按如下方式调用扩展以查找parentView中第一个出现的工具栏: 不幸的是,下面的代码没有编译。我想Kotlin不喜欢使用递归内联函数,但我不能在不内联函数的情况下使用具体化类型 inline fun <reified T> View.findFirstChildRecursive(): T? { when (this) { is T -> return t
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的新手,所以我希望有人能解释原因或提出一个好的解决方案?基本上,Kotlin不允许您内联递归函数,因为它可能需要内联无限多个调用 请参阅此相关帖子: 上述方法也不能是tailrec函数,因为调用自身不是函数中的最后一个操作 请参见此处的Kotlin功能文档: 如果仍然希望实现类似的功能,可以将类传递到函数中 val someView=parentView.findFirstChildRecursiveToolbar::class.java
我想对维克多·伦迪纳的回答补充一点 您可以有两个函数:一个带有clazz:Class参数,另一个与具体化泛型内联:
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
}
提供的答案有帮助吗?@VictorRendina你找到解决办法了吗?我也在尝试做同样的事情。@portfoliobuilder请参阅下面我的答案,了解一个可能的解决方案
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
}
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
}