Epoxyについてはいろいろな記事があるので詳しく説明を省かせていただきますが、RecyclerViewを使いやすくしてくれるライブラリです。今回はEpoxyを使ってRecyclerViewで入力フォームを作ってみたいと思います。LiveData)関連がありそうなものだけ。普段DIライブラリはDagger2を使っているのですが、Koinは使ったことがなかったので今回使ってみました。今回は友人を登録するための連絡帳?の入力画面を作ります。入力項目は以下の通りです。SwitchメモEditText以外にも、よく使うと思われるSwitchも使います。画面は以下のようになります。残念ながらEpoxyのサンプルでEditTextを使った画面を見つけることができませんでした。GitHubのIssuesを検索するといくつか参考になりそうなものがあります。参考になりそうなのは以下のIssueです。forms?このIssueの中で以下のように言われています(多分)EditTextにTextWatcherを登録するモデルの反映はTextWatcherで行う毎入力ごとにモデルに反映していたらリビルドが多発するのでrequestDelayedModelBuildを使うことをお勧めするこのようにする理由はRecyclerViewの破棄・再生成が行われると入力内容が消えてしまうので文字入力が行われるとモデルへの反映が必要になるからだと思います。文字通り、一文字ごとにリビルドしていると頻繁すぎるのでrequestDelayedModelBuildを使って遅延させるということだと思います。単方向とか双方向という言い方が正しいかわからないのですが、ここではユーザー入力を受け付けるモデルを双方向モデルと書きます。モデルの作り方なのですが、いくつかやりかたがあります。カスタムビューで生成する(@ModelViewアノテーションを使う)DataBindingから生成するViewHolderで作る(詳細不明)おそらく双方向の場合@ModelViewアノテーションを使ったカスタムビューで生成する方法が手堅いかと思われます。理由はビューがバインド・アンバインドされるときにリスナーの追加・削除を行う必要があるからです。onUnbindでできるのですが毎回書くのは面倒で、且つ特にonUnbindを忘れやすいと思います。いうわけで、今回はカスタムビューを使って自動生成したモデルを使っていきます。上記の画面ででてきた名項目のようなEditTextが含まれるアイテムは以下のようにして作りました。バインドされたときに@AfterPropsSetアノテーションをつけた関数が実行されます。アンバインドされたときに@OnViewRecycledアノテーションをつけた関数が実行されます。ここで注意なのですが、OnViewRecycledは必ず実行されるわけではないので、例えばですけど必ず実行しなければならない処理などは書かないほうがよいのではないかと思います。アンバインドはRecyclerViewのonViewRecycledが発生すると呼び出されます。EditTextの入力内容の反映はTextWatcherで行っており、上記のIssueで提示されている処理を行っております。上記の画面で出てきた拒否項目のようなSwitchが含まれるアイテムは以下のようにして作りました。基本的にはEditTextのときと変わりません。Epoxy3.4.0からSwitchやCheckBoxで多様すると思われるOnModelCheckedChangeListenerが追加されています。CallbackPropアノテーション等でOnCheckedChangeListenerを指定するとコードジェネレート時にOnModelCheckedChangeListenerになります。OnModelClickListenerのSwitch(等)版です。OnModelCheckedChangeListenerが使われるとコールバックにSwitchの値が渡されます。続いてコントローラーは以下のようになります。setData内が猛烈にこれじゃない感があるのには目をつむっていただいてbuildModels内で項目ごとにモデルを作っています。各項目用のヘッダー、入力項目、Switch等もそれぞれ一つのモデルを再利用しています。この中で性別(Gender)RadioButtonだけは専用用途ですが、もしほかの画面で性別がある場合は再利用可能かと思います。個人的にはレイアウトXMLにScrollViewで項目を書いていくより断然見やすいと思います。レイアウトXMLは長くなれば長くなるほど可読性が悪くなるので、UIがレイアウトXMLに書かれていて振る舞いがコントローラーに書かれているのは、書いていてしっくり感がありました。実はこのフォーム自分の理解不足等により不安定な場合があります。製作中もクラッシュが多発して修正しましたが、漏れている場合があります。OnModelCheckedChangeListenerでクラッシュが発生しました。試行錯誤しながらだったので使い方が間違っている可能性がありますが、今後使っていく中で修正していきます。リスナーは忘れずに解除する特にOnModelCheckedChangeListenerでのクラッシュが多かったのですが、その殆どはOnViewRecycled時にリスナーを解除することで改善しました。今回はRecyclerViewを拡張したEpoxyRecyclerViewを使用しています。EpoxyRecyclerViewを使うとRecyclerViewによく設定する項目が予め設定されていたりEpoxyControllerと接続しやすくなります。RecyclerViewがViewHolder(ここでは便宜上アイテムと呼びます)の再利用を行っているのですが、EpoxyRecyclerViewを使うとデフォルトでは再利用するためのキャッシュ領域(プール)の生存期間がActivityの終了(onDetachedFromWindowでActivityが終了している場合クリアしている)までとなります。同じActivity内でフラグメントを切り替えて再度表示されるときにアイテムが再利用されます。このときに問題が発生します。アイテム内のスイッチも最後の状態のままになっております。再利用されるアイテムが同じ項目にバインドされるとは限らないため、リスナーを解除していないとアイテムが再利用されるときスイッチの状態とモデルの値がことなりonChangeイベントが発生してしまいクラッシュ(IllegalStateExceptionが発生する)します。同じ項目にバインドされた場合はモデルの値とスイッチの状態は一致するのでonChangeイベントは発生しないと思われます。この問題は同じスイッチが含まれるモデルが2つ以上存在する場合に発生すると思われます。ちなみに以下のような例外です。viewOnViewRecycled前に同じアイテムが表示された場合ここで一つ疑問が発生します。OnViewRecycledは必ず呼び出されるわけではないので、OnViewRecycledが呼び出される前に同じアイテムが表示されてしまったらどうなるんだということです。ここまでくるとEpoxyの話ではなくなってRecyclerViewの話になるのですが、結論から言うと新しいアイテムが生成されるので問題ないです。RecylcerViewはViewHolderを再利用するためのキャッシュ領域を持っています。自信がないのですが、おそらくonViewRecycledのタイミングでキャッシュ領域に格納されます。(実際はdispatchViewRecycled内で行われていると思われる・・・)onViewRecycledの前ということはキャッシュ領域にないので、新しいアイテムが生成されます。2秒後にOnViewRecycledが実行されるEpoxyRecyclerViewを使っている場合なのですが、同一ActivityでEpoxyRecyclerViewが含まれるFragmentがdetatchされた場合、デフォルトでは2秒後にonViewRecycledが呼び出されます。これはEpoxyRecyclerView内でRecyclerView#swapAdapterを使ってAdapterを一時退避しているのですが、その処理が2秒遅延されているためです。遅延をやめたい場合はsetDelayMsWhenRemovingAdapterOnDetachに0をセットすればよさそうです。2秒遅延させているのは何か理由があるのでしょうが、そこまではわかりませんでした。まとめEpoxyというよりはRecyclerViewの知識不足によりいろいろ詰まるところはありましたが、新しい書き方を感じることができました。DataBindingを使った場合レイアウトXMLにどうしてもロジックが入り込んで見通しが悪くなることがあります。Epoxyを使うことでレイアウトXMLには表示に関することしか書かなくなり、制御に関わる部分はEpoxyのコントローラー、もしくはEpoxyのモデルに集約されていて書き心地は良かったです。アイテムが最小限になるので1アイテム1機能になり場合によっては再利用もしやすくなるのではないかと思います。アイコンとラベルしか変わらないような設定画面みたいな長い一覧などが作りやすくなると思います。その一方でRecyclerViewの知識がないと不思議な現象に出くわしたときの調査が難しいとも感じました。EpoxyがRecylerViewを使いこなしているという印象を受けました。RecyclerViewの理解も深まりました。今回作った入力フォームはサンプルの領域を出ていないと思いますが、今後もう少し使ってみて知見を得たいと思います。ソースコードはGitHubにアップロードしてあります。コメントをキャンセルメールアドレスが公開されることはありません。Web業界でJava(Kotlin)でDIしようと思ったらSpringが有名だと思います。...Android既存アプリのレイアウトをConstraintLayoutに書き換えた会社で作っているサービスのAndroidアプリにConstraintLayoutが未導入だったので多くの画面をConstraintLayoutで書き直しました。Truthを使ってみるAndroidXのTestではGoogleのアサーションライブラリのTruthが使われるみたいです。今、自分が会社で作っているアプリはPush通知が届かないとサービスが成り立たない重要な通知となっております。Messaging(FCM)を使っています。...AndroidJetpackのWorkManagerのメモJetpackのWorkManagerのメモです。AFFINGER5.。