Purusann
Purusann

Reputation: 13

How can i refactor the navigation drawer

I would like to refactor this section of code as you can see there's a lot of functions repeatly

override fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
        when (menuItem.itemId) {

            R.id.home -> {
                homeFragment = HomeFragment()
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.frame_layout, homeFragment)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit()
            }

            R.id.loanable -> {
                loanableFragment = LoanableFragment()
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.frame_layout, loanableFragment)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit()
            }

            R.id.payable -> {
                payableFragment = PayableFragment()
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.frame_layout, payableFragment)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit()
            }

            R.id.compare_rate -> {
                compareRateFragment = CompareRateFragment()
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.frame_layout, compareRateFragment)
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit()
            }
        }

        drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }

Upvotes: 1

Views: 116

Answers (2)

xinaiz
xinaiz

Reputation: 7788

Why not use enum and some cool language features!

enum class NavigationItem(@IdRes val id: Int, val createFragment: ()-> Fragment) {
  HOME(R.id.home, ::HomeFragment),
  LOANABLE(R.id.loanable, ::LoanableFragment),
  PAYABLE(R.id.payable, ::PayableFragment),
  COMPARE_RATE(R.id.compare_rate, ::CompareRateFragment)
}

override fun onNavigationItemSelected(menuItem: MenuItem) =
  requireNotNull(enumValues<NavigationItem>().find { it.id == menuItem.itemId })
    .createFragment()
    .let { fragment ->
       supportFragmentManager
         .beginTransaction()
         .replace(R.id.frame_layout, fragment)
         .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
         .commit()
       drawerLayout.closeDrawer(GravityCompat.START)
    }.run { true }

That's all ;)

The enum contains menu itemId and target fragment constructor reference. The line:

requireNotNull(enumValues<NavigationItem>().find { it.id == menuItem.itemId })

searches the enum for entry that has the same id as selected menuItem. If no entry is found, exception is thrown. Line:

createFragment()

simply invokes constructor reference of fragment from the enum entry, creating new fragment instance. Fragment transaction should be understandable. The last line:

run { true }

returns true from function as in original code.

Upvotes: 1

Son Huynh
Son Huynh

Reputation: 939

You can use kotlin extension function to make your code more clearly.

fun Fragment.replace() {
    supportFragmentManager
             .beginTransaction()
             .replace(R.id.frame_layout, this)
             .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
             .commit()
}

override fun onNavigationItemSelected(menuItem: MenuItem): Boolean { 
    when (menuItem.itemId) {
        R.id.home -> HomeFragment().replace()
        R.id.loanable -> LoanableFragment().replace()
        R.id.payable -> PayableFragment().replace()
        R.id.compare_rate -> CompareRateFragment().replace()
    }
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}

If your fragment container id is different:

infix fun Fragment.replaceTo(id: Int) {
    supportFragmentManager
             .beginTransaction()
             .replace(id, this)
             .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
             .commit()
}

override fun onNavigationItemSelected(menuItem: MenuItem): Boolean { 
     when (menuItem.itemId) {
        R.id.home -> HomeFragment() replaceTo R.id.frame_layout1
        R.id.loanable -> LoanableFragment() replaceTo R.id.frame_layout2
        R.id.payable -> PayableFragment() replaceTo R.id.frame_layout3
        R.id.compare_rate -> CompareRateFragment() replaceTo R.id.frame_layout4
    }
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}

Upvotes: 1

Related Questions