【问题标题】:What to return in this recursive method?在这个递归方法中返回什么?
【发布时间】:2020-10-22 07:31:40
【问题描述】:

我正在创建一种在ArrayList 中递归搜索View 的方法。它将遍历这个ArrayList,如果它包含ArrayList,它也会搜索Views,依此类推,直到找到一个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 找到的任何东西都将被退回,我到底应该返回什么?

【问题讨论】:

  • someArrayList中的多视图是否有任何变化,那么应该返回哪个?
  • 哦,对了。我现在添加了一个forEach,所以它会循环遍历每个someArrayList 的项目以搜索视图以使其不可见。
  • 相反,您可以在 searchForView 中使视图不可见,请参阅下面的解决方案
  • 不是问题的答案,但应该是 searchForView(item) 而不是 item.forEach { searchForView(it as ArrayList&lt;*&gt;) }

标签: android kotlin recursion arraylist return


【解决方案1】:

你可以在函数内部设置而不返回任何东西

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(item) 而不是@IR42 建议的item.forEach { searchForView(it as ArrayList&lt;*&gt;) },因为您不知道arraylist 中的每个项目是否都是arraylist。

【讨论】:

    【解决方案2】:

    我之前也尝试过和你一样的事情 这就是我所做的

    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 和 google 按钮再次可见

    如果您想修复自己的代码,我会这样做

    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
    

    【讨论】:

      【解决方案3】:

      您的函数不可编译,因为它应该返回一个视图,但您没有在 else 分支中返回一个视图,或者如果您到达输入列表的末尾却没有找到一个视图。

      但是,如果这个函数所做的只是返回一个视图,那么设置 所有 视图的可见性的要求就无法满足您的要求。它只会返回一个视图。

      相反,您可以将函数参数传递给它找到的每个视图要做什么。无需退货。

      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
      }
      

      如果嵌套非常深,您可能希望将此函数重新排列为尾递归,如下所示:

      tailrec fun List<*>.forEachViewDeep(block: (View) -> Unit) {
          for (item in this) {
              if (item is View)
                  block(item)
          }
          filterIsInstance<ArrayList<*>>().flatten().forEachViewDeep(block)
      }
      

      【讨论】:

        猜你喜欢
        • 2021-05-12
        • 2013-10-14
        • 2019-06-26
        • 1970-01-01
        • 1970-01-01
        • 2022-11-12
        • 2022-01-17
        • 1970-01-01
        • 2023-04-09
        相关资源
        最近更新 更多