【问题标题】:Any code improvement in adding/replacing fragment添加/替换片段的任何代码改进
【发布时间】:2018-01-24 14:35:18
【问题描述】:

我已经开始学习 Kotlin,但不知道该语言的所有功能。

该函数用于在FrameLayout中显示片段。逻辑是这样的,第一次它应该总是add()片段,下一次它会replace()。另外在某些情况下我需要使用addToBackStack() 并且在相同的情况下也需要禁用左侧菜单。

fun showFragment(fragment : Fragment,
                 isReplace: Boolean = true,
                 backStackTag: String? = null,
                 isEnabled: Boolean = true)
{
    /* Defining fragment transaction */
    val fragmentTransaction = supportFragmentManager
            .beginTransaction()

    /* Select if to replace or add a fragment */
    if(isReplace)
        fragmentTransaction.replace(R.id.frameLayoutContent, fragment, backStackTag)
    else
        fragmentTransaction.add(R.id.frameLayoutContent, fragment)

    /* Select if to add to back stack */
    if(backStackTag != null)
        fragmentTransaction.addToBackStack(fragment.javaClass.name)

    fragmentTransaction.commit()
    enableDrawer(isEnabled)
}

问题:是否有可能对 Kotlin 语言规范相关的函数代码进行一些改进,以使代码更清晰,因为现在函数看起来像一个整体。

【问题讨论】:

    标签: android android-fragments kotlin


    【解决方案1】:

    我已经发布了blog 关于以下答案。

    我会将Extension function 写入FragmentManager,它接受Lambda with Receiver 作为参数。

    inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> Unit) {
        val fragmentTransaction = beginTransaction()
        fragmentTransaction.func()
        fragmentTransaction.commit()
    }
    

    要添加fragment,我们现在可以像这样从Activity 调用:

    supportFragmentManager.inTransaction {
        add(R.id.frameLayoutContent, fragment)
    }
    

    这样做的好处是我们现在不必每次添加或替换Fragment 时都调用beginTransaction()commit()。您浪费了多少时间调试才发现您错过了在 Java 中调用 commit()

    接下来,我会写Extension functionsAppCompatActivity

    fun AppCompatActivity.addFragment(fragment: Fragment, frameId: Int, backStackTag: String? = null) {
        supportFragmentManager.inTransaction {
            add(frameId, fragment)
            backStackTag?.let { addToBackStack(fragment.javaClass.name) }
        }
    }
    
    fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int, backStackTag: String? = null) {
        supportFragmentManager.inTransaction {
            replace(frameId, fragment)
            backStackTag?.let { addToBackStack(fragment.javaClass.name) }
        }
    }
    

    现在我们可以在一行中从任何Activity 添加/替换Fragment,而无需任何额外的限定符:

    addFragment(yourFragment, R.id.frameLayoutContent, "tag")
    
    replaceFragment(yourFragment, R.id.frameLayoutContent, "tag")
    

    【讨论】:

    【解决方案2】:

    当我有一些与使用大量变量和null checks相关的代码时,我喜欢使用withlet

    所以我会这样做:

    fun showFragment(fragment : Fragment,
                     isReplace: Boolean = true,
                     backStackTag: String? = null,
                     isEnabled: Boolean = true)
    {
        /* Defining fragment transaction */
        with(supportFragmentManager.beginTransaction()) {
    
            /* Select if to replace or add a fragment */
            if(isReplace)
                replace(R.id.frameLayoutContent, fragment, backStackTag)
            else
                add(R.id.frameLayoutContent, fragment)
    
            /* Select if to add to back stack */
            backStackTag?.let { addToBackStack(it) }
    
            commit()
        }
        enableDrawer(isEnabled)
    }
    

    【讨论】:

      【解决方案3】:

      一切都很好。应该是这里

      if(backStackTag != null)
          fragmentTransaction.addToBackStack(fragment.javaClass.name)
      

      您想像这样使用backStackTag 添加片段

      if(backStackTag != null)
          fragmentTransaction.addToBackStack(backStackTag)
      

      【讨论】:

        【解决方案4】:

        你可以像这样创建一个扩展函数:

        1. 如果您希望使用supportFragmentManager(使用支持库)而不是fragmentManager,使您的应用与运行系统版本低至Android 1.6的设备兼容,请导入android.support.v4.app.FragmentManagerandroid.support.v4.app.FragmentTransaction

        2. 在顶层定义以下函数,即直接在包下:

          inline fun FragmentManager.inTransaction(func: FragmentTransaction.() Unit) {
              val fragmentTransaction = beginTransaction()
              fragmentTransaction.func()
              fragmentTransaction.commit() 
          }
          
        3. 从任何活动调用函数:

          supportFragmentManager.inTransaction {
              add(R.id.frameLayoutContent, fragment)
          }
          

        【讨论】:

          【解决方案5】:

          您可以使用以下代码进行替换:

          fun Fragment.moveAnotherFragment(fragment: Fragment,addToBackStack: Boolean = true, func : Bundle?. () -> Unit = {}) {
          
          fragment.enterTransition =
              activity?.supportFragmentManager?.beginTransaction()?.apply {
                  replace(
                      R.id.frame, fragment.apply {
                          enterTransition = Slide(Gravity.END)
                          exitTransition = Slide(Gravity.START)
                          arguments.apply(func)
                      }
                  )
                  if (addToBackStack) addToBackStack(null)
                  commit()
              }
          

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-12-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多