[英]What to return in this recursive method?
我正在创建一种方法来递归搜索ArrayList
内的View
。 它将遍历这个ArrayList
,如果它包含一个ArrayList
,它也会搜索View
,依此类推,直到找到要返回的View
。 这样我就可以使里面的任何View
都不可见。
fun searchForView(arrayList: ArrayList<*>): View {
arrayList.forEach { item ->
if (item is View) {
return item
} else if (item is ArrayList<*>) {
item.forEach {
searchForView(it as ArrayList<*>)
}
}
}
} // Error here, needs to return a View
所以我会这样使用它:
someArrayList.forEach {
searchForView(someArrayList).visibility = View.INVISIBLE
}
但是它给了我一个错误,因为在方法的末尾需要有一个return someView
语句。 每当我调用它时,被搜索的ArrayList
总是有一个View
。 那么我应该在最后返回什么,知道View
找到的任何东西都将被返回?
您可以在 function 内部设置并且不返回任何内容
fun searchForView(arrayList: ArrayList<*>){
arrayList.forEach { item ->
if (item is View) {
item.visibility = View.INVISIBLE // set here
} else if (item is ArrayList<*>) {
item.forEach {
searchForView(it as ArrayList<*>)
}
}
}
}
您应该使用 searchForView searchForView(item)
而不是item.forEach { searchForView(it as ArrayList<*>) }
正如@IR42 建议的那样,因为您不知道 arraylist 中的每个项目是否是 arraylist 。
我以前也想做和你一样的事情,这就是我所做的
class VisibilitySwitcher(private val mutableViewSet: MutableSet<View?>, private val onCondition: Boolean = true){
fun betweenVisibleOrGone(){
if(onCondition)
mutableViewSet.forEach {
when (it?.visibility) {
View.VISIBLE -> {it.visibility = View.GONE}
View.GONE -> {it.visibility = View.VISIBLE}
}
}
}
fun betweenVisibleOrInvisible(){
if(onCondition)
mutableViewSet.forEach {
when (it?.visibility) {
View.VISIBLE -> {it.visibility = View.INVISIBLE}
View.INVISIBLE -> {it.visibility = View.VISIBLE}
}
}
}
fun betweenInVisibleOrGone(){
if(onCondition)
mutableViewSet.forEach {
when (it?.visibility) {
View.INVISIBLE -> {it.visibility = View.GONE}
View.GONE -> {it.visibility = View.INVISIBLE}
}
}
}
}
使用示例
class LoginActivity : BaseActivity() {
@Inject
@ViewModelInjection
lateinit var viewModel: LoginVM
private lateinit var mutableViewSet: MutableSet<View?>
override fun layoutRes() = R.layout.activity_login
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
facebookBtn.setOnClickListener { handleClickEvent(it) }
googleBtn.setOnClickListener { handleClickEvent(it) }
}
private fun handleClickEvent(view: View) {
when (view) {
facebookBtn -> { viewModel.smartLoginManager.onFacebookLoginClick() }
googleBtn -> { viewModel.smartLoginManager.onGoogleLoginClick() }
}
mutableViewSet = mutableSetOf(facebookBtn, googleBtn, progressBar)
VisibilitySwitcher(mutableViewSet).betweenVisibleOrGone() // <----- Use without Condition
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
VisibilitySwitcher(mutableViewSet, resultCode != -1).betweenVisibleOrGone() //<-- Use with Conditions
viewModel.smartLoginManager.onActivityResultCallBack(requestCode, resultCode, data)
super.onActivityResult(requestCode, resultCode, data)
}
}
关键是每当您从 facebook 或 google 按钮单击登录时,它将设置 facebook 和 google 的可见性消失并设置进度条(进度条的默认值为 View.GONE)可见
在覆盖 fun onActivityResult() 如果结果代码不是 -1 这意味着它有一些错误或取消,因此它将切换回进度条消失并更改 facebook 和谷歌按钮再次可见
如果您想修复自己的代码,我会这样做
fun searchForView(mutableViewSet: MutableSet<View?>){
mutableViewSet.forEach {
when (it?.visibility) {
View.VISIBLE -> {it.visibility = View.INVISIBLE}
View.INVISIBLE -> {it.visibility = View.VISIBLE} //<-- you can delete this if you don't want
}
}
}
或非常短的形式
fun searchForView(mutableViewSet: MutableSet<View?>) = mutableViewSet.forEach { when (it?.visibility) {View.VISIBLE -> it.visibility = View.INVISIBLE } }
用法
val mutableViewSet = mutableSetOf(your view1,2,3....)
searchForView(mutableViewSet)
如果它必须使用 arrayList: ArrayList<*> 然后
fun searchForView(arrayList: ArrayList<*>) = arrayList.forEach{ if (it is View) it.visibility = View.INVISIBLE
您的 function 是不可编译的,因为它应该返回一个视图,但是您没有在else
分支中返回一个视图,或者如果您在没有找到视图的情况下到达输入列表的末尾。
但是,如果所有这些 function 确实返回一个视图,那么设置所有视图的可见性的要求不可用。 它只会返回一个视图。
相反,您可以传递一个 function 参数来了解如何处理它找到的每个视图。 没有必要退回任何东西。
fun ArrayList<*>.forEachViewDeep(block: (View) -> Unit) {
for (item in this) when (item) {
is View -> block(item)
is ArrayList<*> -> item.forEachViewDeep(block)
}
}
并像这样使用它:
someArrayList.forEachViewDeep {
it.visibility = View.INVISIBLE
}
如果嵌套非常深,您可能需要重新排列此 function 为尾递归,如下所示:
tailrec fun List<*>.forEachViewDeep(block: (View) -> Unit) {
for (item in this) {
if (item is View)
block(item)
}
filterIsInstance<ArrayList<*>>().flatten().forEachViewDeep(block)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.