AnkoでLayout XMLを殺した

そういえば先月頭にRettyさんでAnkoについてLTしたのでスライド置いておきますね。

あ、ちなみに本稿は特にAnkoの解説は行ってないポエムです。

Ankoとは

Kotlin製DSL。Viewを書くのに利用します。
XMLでView書いた場合の以下のような問題を感じてJetBrainsのエンジニアが開発したのがAnko。

  • 型安全じゃないし
  • null安全じゃないし
  • 似たようなことを毎回かかなきゃいけないし
  • XMLをパースする分パフォーマンス悪いし
  • コードの再利用できないし

こんな感じでViewを書けます

verticalLayout {
    val name = editText()
    button("Say Hello") {
        onClick { toast("Hello, ${name.text}!") }
    }
}

Javaで書いた場合との差が冒頭に貼ったスライドに書いてあるので、興味ある人は見てください。

なにこれ魔法!?🎩

Kotlinの拡張関数とプロパティを利用してます。 拡張関数を引数にとる関数がどうたらこうたら。これも冒頭のスライドに書いてあるので興味のある人は見てください。

XML全部殺してフルAnkoにした

mints-Android-LayeredArchitecture 暇な時に開発してるアプリのViewをすべてAnkoで書いてみました。 (まだ改善できそうなところは多い)

(追記)
HEADではもう、LayoutXMLとDatabindingを利用する形に書き換えてしまった。

ActivityやFragmentとは別のファイルにViewをまとめる

AnkoでViewを書いてる部分

class MainUi : AnkoComponent<MainActivity> {
    private lateinit var viewPager: ViewPager

    override fun createView(ui: AnkoContext<MainActivity>): View = with(ui) {
        verticalLayout {
            val tabLayout = tabLayout {
                tabMode = TabLayout.MODE_SCROLLABLE
                tabGravity = TabLayout.GRAVITY_FILL
                setSelectedTabIndicatorColor(getColor(ctx, R.color.colorPrimary))
            }.lparams(width = matchParent, height = wrapContent)

            viewPager = viewPager {
                id = 1
                offscreenPageLimit = 2
            }.lparams(width = matchParent, height = matchParent)

            tabLayout.setupWithViewPager(viewPager)
        }
    }

    fun showPages(fm: FragmentManager, pages: List<PageAdapter.Page>) {
        viewPager.adapter = PageAdapter(fm, pages)
    }
}

利用側

class MainActivity: AppCompatActivity() {
    private val ui = MainUi()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ui.setContentView(this)
    }
}

XMLを書かなくていいのは結構いいですね。今回は一人での実装だったのでただの予想ですが、コードレビューでXMLを読むのが辛いのですが、Ankoなら多少軽減されるかも。 もっと細かい単位でAnkoComponentを実装していけばコードのreuseができそう。