Reputation: 13
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
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
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