投稿

3月, 2020の投稿を表示しています

LVMC (a.k.a. MVVM: ViewModel + DataBinding) と Fat View

LVMC(Android の MVVM)モデル や DataBinding について大体の感じはつかめてきたが、先日、一つ失敗して、学習したことがあった。 ViewModel + DataBinding を使うことによって、LifeCycle でグチャグチャに分断された Activity のあちこちに詰め込まれたコードを ViewModel や View に退避して、Activity をスッキリさせることには成功した。 一方、Activity から追い出したコードを、ViewModel に所属させるのか、View に所属させるのかという部分で間違いを犯した。DataBinding で View のプロパティを LiveData でリアルタイムに反映させることができるのだからと、ほとんどの部分を View に移植したのだ。これが失敗だった。 これは ViewModel が導入される以前の、Activity の肥大化に悩んだ当時の開発者たちが採った Fat View と呼ばれるアプローチと同じもので、Activity が一手に引き受けていた複雑な処理を、View が肩代りするだけの話に過ぎない。もちろん、通常は、Activity と View は一対多の関係だから、Activity に複数の View にまつわる処理が集結するよりはマシだが、単純に View の数に分割されただけで、全体としての複雑さの総量に変化はない。 今回は ViewModel を使っているにもかかわらず、単なる Fat View 的なアプローチと同じ罠に陥るという過ちを犯してしまったわけである。 Fat View の何がいけないかというと、View のプロパティにセットした値が、View で処理される順序が、何ら保証されていないという点である。今回は、ImageView を拡張して、Glide によるリモート画像の読み込みを行うようなことを実現したかったのだが、リモートのアドレスをバインドされた LiveData を通じてダイナミックに設定しようとした。ところが、リモートのアドレスをいくつかの諸条件から組み合わせて動的な生成を行う処理を View 内部に持たせ、バラバラの諸条件を View のプロパティとして入力しようとしたため、アドレスが null の段階で Glide で読み込もうと

LVMC (a.k.a. MVVM) サンプル

前日の記事「 Android で MVVM ならぬ“LMVC” 」のサンプルコード build.gradle (:app): plugins { id 'com.android.application' } android { compileSdkVersion 30 buildToolsVersion '30.0.3' defaultConfig { applicationId 'com.scaredeer.lvmcsample' minSdkVersion 26 targetSdkVersion 30 versionCode 1 versionName '1.0' } compileOptions { sourceCompatibility 1.8 targetCompatibility 1.8 } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } buildFeatures { dataBinding true } } dependencies { implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' // https://developer.android.com/jetpack/androidx/releases/lifecycle#java implementation 'androidx.li

Android で MVVM ならぬ“LMVC”

イメージ
MVC と MVVM(参考: 2015年に備えて知っておきたいリアクティブアーキテクチャの潮流 )の比較: やはり、MVC の場合と MVVM の場合で、Model の意味合いが変っており、MVVM の方の M は基本的にもう Model と呼ぶべきものではないものとなっていると思う。 基本的にプレゼンテーション層とデータ・ビジネスロジック層を分けるという観点で全体を階層化させているわけだから、MVC のように、入力と出力を分けるという観点とは根本的に異っている。MVC の場合は、入力を抽象化して内部データ化するという処理の部分と、内部データを具象化して出力するという処理の部分を交錯させないで分離するという観点で、その抽象化された内部データの属する部分を Model と呼んでいるわけだ。 なので、MVC と MVVM で名称的に共通するのは View だけであり、Model 部分は紛らわしいので、別のネーミングにすべきではなかったかと思う。むしろ、ViewModel の部分の方が、View にとっての抽象化されたデータの参照元(Model of View となる部分)としての意味で ViewModel と呼ぶのは、まだ理解しうる。Model の方は Model と呼ばずに、Logic などと名付けて LVVM とでもすべきではなかったのだろうか(LVVM では別のタームと被ってしまうから、ViewModel の方をこそ Model と呼んで、LMV (Logic-Model-View) とか LMVC (Logic-Model-ViewControl) でもいいんじゃないかと思う)。 なので以下、敢えて LMVC の用語で行こうと思うが、Logic 層と ViewControl 層の両者の中間に Model 層(俗に言う ViewModel)を設ける意義は、処理の時系列的な連動性を断ち、時間的なバッファを設けることが可能となるからだと思う。ネットワークの非同期処理などを抱える Logic 層、Activity のライフサイクルなどによって頻繁にアプリ外の都合と要因で破棄・再生成されるライフサイクルを持つ ViewControl 層で、それぞれが所属する時間の流れ、ライフサイクルの様相が大きく食い違っており、この異なるフェイズが混じり合うことないように