何が起きる?
ちょっと昔のネタなのですが、時々忘れて使いそうになるので、簡単にメモしておきます。
Kotlinではviewへのアクセス時にfindViewByIdしてくれるように、こんな感じで遅延初期化して利用することができます。
private val toolbar by lazy {
view!!.findViewById<Toolbar>(R.id.toolbar)
}
ただlazyを使うと一度取得したものをメンバ変数として保持し、次に利用するときも同じインスタンスを返します。
ここでFragmentのライフサイクルを思い出すと、以下のようにバックスタックから返ってきた時に、onCreateView()がまた呼ばれます。
onCreateViewでレイアウトを新しく作って返すと、、メンバ変数で持っているViewは前に作ったレイアウトなので、リークします。また、textView.text = "hoge"などしてもレイアウトの見た目に反映されません。
ではどうするべき?
ここにそれぞれの方法のメリデメがまとまっています。
https://discuss.kotlinlang.org/t/pros-cons-of-android-view-access-strategies/3160
- 現状、lateinitが一般的っぽい?です
- 一応、Kotlin Android Extensionでもちゃんとやってそうな雰囲気です。
- Architecture ComponentのLifecycleOwnerとKotterKnifeを利用することができれば、以下のコードでできそうです。
https://gist.github.com/chrisbanes/fc4392dcbdc0aa5d99147dc551616676
元ネタ