繁体   English   中英

在这个递归方法中返回什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM