LoginSignup
0
1

More than 3 years have passed since last update.

[メモ]Bottom Navigation ActivityのKotlinボイラープレートをリファクタリング

Last updated at Posted at 2018-09-07

Bottom Navigation Activity を自動生成すると、こんな感じのソースが生成される。

Kotlin 初学者のため勘所を外していたら申し訳ないのだけれど、僕個人の趣味にあわせて書き換えてみたい。

class HomeActivity : AppCompatActivity() {

    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_home -> {
                message.setText(R.string.title_home)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_dashboard -> {
                message.setText(R.string.title_dashboard)
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_notifications -> {
                message.setText(R.string.title_notifications)
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)

        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
    }
}

イベントリスナーの持ち上げ

OnNavigationItemSelectedListenerprivate val として、初期化と同時に構築され変更不能なフィールドとして確保されていることは好感が持てる。
ところでアクティビティを想定すると、ナビゲーションは一つ。(二つ以上のナビゲーションが画面内に存在するのは、 UI として下品だろう)

つまりリスナーを独立させる必要はなく、このアクティビティが唯一持つナビゲーションのリスナーであればよい。

class HomeActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)

        navigation.setOnNavigationItemSelectedListener(this)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.navigation_home -> {
                message.setText(R.string.title_home)
                return true
            }
            R.id.navigation_dashboard -> {
                message.setText(R.string.title_dashboard)
                return true
            }
            R.id.navigation_notifications -> {
                message.setText(R.string.title_notifications)
                return true
            }
        }
        return false
    }
}

テキスト設定のくくりだし

さて。 onNavigationItemSelected は内側の when の各 case がほとんど同じ構造であることに気づく。

こういう場合はくくりだしだ。

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        var resId: Int?
        when (item.itemId) {
            R.id.navigation_home -> resId = R.string.title_home
            R.id.navigation_dashboard -> resId = R.string.title_dashboard
            R.id.navigation_notifications -> resId = R.string.title_notifications
            else -> resId = null
        }
        resId?.let {
            message.setText(resId)
            return true
        }
        return false
    }

そして when を関数としてくくり出すことで、さらに整理できる。


    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        return stringIdFrom(item.itemId)?.let {
            message.setText(it)
            true
        } ?: false
    }

    private fun stringIdFrom(itemId: Int): Int? {
        return when (itemId) {
            R.id.navigation_home -> R.string.title_home
            R.id.navigation_dashboard -> R.string.title_dashboard
            R.id.navigation_notifications -> R.string.title_notifications
            else -> null
        }
    }

整理し終えたコード

掲げるまでもないけれど、全体はこう変わる。

class HomeActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)

        navigation.setOnNavigationItemSelectedListener(this)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        return stringIdFrom(item.itemId)?.let {
            message.setText(it)
            true
        } ?: false
    }

    private fun stringIdFrom(itemId: Int): Int? {
        return when (itemId) {
            R.id.navigation_home -> R.string.title_home
            R.id.navigation_dashboard -> R.string.title_dashboard
            R.id.navigation_notifications -> R.string.title_notifications
            else -> null
        }
    }
}

ネストの深さから見ても、スッキリしたのではないだろうか?

アプリケーションで繰り返し利用されるようならば stringIdFrom を共通で使う「関数オブジェクト」として切り出してもいいだろう。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1