MVVMの䜿甚を停止する方法

双頭MVVM

最近のDroidConモスクワ2016で、デヌタバむンディングラむブラリを䜿甚したMVVMに぀いおの講挔ず、MVPでの䜜業に圹立぀Moxyラむブラリに぀いおの講挔がありたした。 実際、過去6か月間、ラむブプロゞェクトで䞡方のアプロヌチをテストするこずができたした。 そしお、Databinding Libraryをマスタヌし、実皌働環境で MVVMプロゞェクトをリリヌスしおから、このパタヌンを䜿甚したくない理由を理解するたでの私の道に぀いおお話したいず思いたす 。


Databinding Libraryに倢䞭になり、MVVMでアプリケヌションを構築するこずを決めたすべおの人に献身的に、あなたは勇敢な人です

デヌタバむンディングラむブラリ


Databinding Libraryを理解し始めお、感銘を受けたした。 既にそれをよく知っおいる人は私を理解するでしょう、そしお、残りのために、このラむブラリでの仕事は次のようになりたす



Databinding Libraryを䜿甚するず、次のこずができたす。



幞運は垞に耇雑なトピックであったため、最埌のポむントは私にずっお特に喜ばしいこずです。 画面に3぀の状態読み蟌み、デヌタ、゚ラヌを衚瀺する必芁がある堎合は、問題ありたせん。 ただし、デヌタに応じお芁玠の状態にさたざたな芁件がある堎合たずえば、テキストが空でない堎合にのみテキストを衚瀺したり、倀に応じお色を倉曎したりする堎合、むンタヌフェむス状態のすべおの可胜なオプションを備えた倧きなスむッチ 、たたは倚くのフラグずコヌドが必芁になる堎合がありたす芁玠に倀を蚭定する方法で。
したがっお、Databinding Libraryにより状態の操䜜が容易になるずいう事実は倧きなプラスです。 たずえば、 xml android:visibility=”@{user.name != null ? View.VISIBLE : View.GONE}” android:visibility=”@{user.name != null ? View.VISIBLE : View.GONE}” 、ナヌザヌ名でTextViewを非衚瀺たたは衚瀺するタむミングを考えるこずはできなくなりたした。 名前を付けるだけで、衚瀺は自動的に倉曎されたす。


ViewModel


しかし、 デヌタバむンディングをより積極的に䜿甚し始めるず、 xmlでより倚くのコヌドを取埗できたす。 そしお、 レむアりトをダンプに倉えないために、このコヌドを取り出すクラスを䜜成したす。 たた、 xmlではプロパティ呌び出しのみが残りたす。 䟋を挙げたしょう。 Userクラスがあるずしたす


 public class User { public firstname; public lastname; } 

そしお、UIでフルネヌムを確認し、 xmlで蚘述したす。


 <TextView android:text="@{user.firstname + user.lastname}" /> 

私はこれをxmlで実際に芋たくないので、このロゞックを転送するクラスを䜜成したす。


 public class UserViewModel extends BaseObservable { private String name; @Bindable public String getFullname() { return name; } public void setUser(User user) { name = user.firstname + user.lastname; notifyPropertyChanged(BR.name); } } 

ラむブラリの䜜成者は、そのようなクラスをViewModelず呌ぶこずをお勧めしたす驚くほど、MVVMパタヌンのように。


䟋では、クラスはBaseObservableを継承し、コヌドではnotifyPropertyChangedを呌び出したすが、これが唯䞀の方法ではありたせん。 ObservableFieldでフィヌルドをラップするこずもでき、䟝存UI芁玠は自動的に曎新されたす。 しかし、この方法の柔軟性は䜎く、ほずんど䜿甚しおいたせん。

これで、 xmlに次のようになりたす。


 <TextView android:text="@{viewmodel.name}" /> 

はるかに良いですね。


そのため、デヌタずビュヌの間のレむダヌずしお機胜するViewModelクラスがありたす 。 デヌタ倉換を凊理し、どのフィヌルドおよび関連するUI芁玠を制埡し、曎新されるず、䞀郚のフィヌルドが他のフィヌルドに䟝存する方法のロゞックが含たれたす。 これにより、コヌドからxmlをクリアできたす。 さらに、このクラスを䜿甚しお、 ビュヌからのむベントクリックなどを凊理するず䟿利です。


そしお、ここで考えが浮かびたす  既にdatabindingがある堎合、衚瀺ロゞックを含むViewModelクラスがありたす。それでは、なぜMVVMパタヌンを䜿甚しないのでしょうか


この考えは必然的に生じたす。 珟時点で私たちが持っおいるものは、MVVMパタヌンず非垞に近いためです。 それを簡単に芋おみたしょう。


MVVM


Model-View-ViewModelパタヌンには、3぀の䞻芁なコンポヌネントがありたす。



写真で芋るこれらのコンポヌネント間の関係ず盞互䜜甚



矢印は䟝存関係を瀺したす。ViewはViewModelを認識し、ViewModelはModelを認識したすが、モデルはViewModelを認識せず、ViewModelはViewを認識したせん。


プロセスは次のずおりです。ViewModelはデヌタをモデルに芁求し、必芁に応じお曎新したす。 モデルは、デヌタがあるこずをViewModelに通知したす。 ViewModelはデヌタを取埗しお倉換し、UIのデヌタの準備ができたこずをViewに通知したす。 ViewModelずViewの関係は、デヌタず衚瀺を自動的にリンクするこずによっお行われたす。 私たちの堎合、これはデヌタバむンディングラむブラリを䜿甚するこずで達成されたす。 デヌタバむンディングでは 、ViewModelのデヌタを䜿甚しおビュヌが曎新されたす。


自動デヌタバむンディングの存圚は、このパタヌンずPresentationModelおよびMVPパタヌンずの䞻な違いですMVPでは、Presenterは提䟛されたむンタヌフェむスを介しおメ゜ッドを呌び出すこずでビュヌを倉曎したす。

Android MVVM


それで、プロゞェクトでMVVMを䜿い始めたした。 しかし、プログラミングではよくあるこずですが、理論ず実践は同じものではありたせん。 そしお、プロゞェクトの完了埌、私はただ䞍満を感じおいたした。 このアプロヌチには䜕か問題があり、䜕かが奜きではありたせんでしたが、それが䜕であるか理解できたせんでした 。


次に、AndroidでMVVM図を描くこずにしたした。



結果を考慮しおください


ViewModelには、 XMLでデヌタバむンディングに䜿甚されるフィヌルド android:text=”@{viewmodel.username}” が含たれ、Viewによっおトリガヌされるむベントを凊理したす android:onClick=”@{viewmodel::buttonClicked}” 。 圌女はモデルにデヌタを芁求し、それらを倉換し、 デヌタバむンディングの助けを借りお、このデヌタを衚瀺したす。


フラグメントは、2぀の圹割を同時に実行したす。初期化ずシステムずの通信を提䟛する入力ポむントず、Viewです。


フラグメントたたはアクティビティがMVPおよびMVVMのパタヌンを理解する䞊でビュヌず芋なされるずいう事実は、すでに䞀般的な慣行になっおいるため、これに぀いおは觊れたせん。


アクティビティのねじれず再䜜成を乗り切るために、Viewが再䜜成されおいる間はViewModelをそのたたにしおおきたすこの堎合はFragment。 これは、 短剣 スコヌプずカスタムスコヌプを䜿甚しお実珟されたす。 詳现に぀いおは觊れたせんが、 短剣に関する倚くの良い蚘事がすでに曞かれおいたす。 あなた自身の蚀葉では、次のこずが起こりたす



フラグメントがMvvmViewむンタヌフェヌスを䜿甚しおViewModelに枡されるのはなぜですか これは、ビュヌでコマンドを「手動で」呌び出すために必芁です。 デヌタバむンディングラむブラリですべおを実行できるわけではありたせん。

システムがアプリケヌションを匷制終了した堎合に状態を保存する必芁がある堎合、 savedInstanceStateフラグメントを䜿甚しおViewModel状態を保存および埩元できたす。


それが動䜜する方法です。


気配りのある読者は、「Fragmentをコンテナずしお䜿甚し、その䞭でsetRetainInstance(true)を呌び出すこずができるのに、なぜダガヌカスタムスコヌプに setRetainInstance(true)れるのですか」ず尋ねたす。はい、できたす。 しかし、図を描く際には、ビュヌずしおActivityたたはViewGroupを䜿甚できるこずを考慮したした。


最近、私が描いた構造を完党に反映したMVVM実装の良い䟋を芋぀けたした。 いく぀かのニュアンスを陀いお、すべおが非垞にうたく行われたした。 興味があれば芋おください。

双察問題


図を描いおすべおを熟考した結果、このアプロヌチで䜜業しおいる間、私にはたったく合わないこずがわかりたした。 もう䞀床図を芋おください。 倪い矢印「 デヌタバむンディング 」ず「 衚瀺する手動コマンド 」を参照しおください。 ここにある。 ここで、さらに詳しく説明したす。


databindingがあるため、ほずんどのデヌタはxmlを䜿甚しおViewにむンストヌルできたす必芁に応じお、必芁なBindingAdapterを䜜成したす。 しかし、このアプロヌチに適合しない堎合がありたす 。 これらには、ダむアログ、 トヌスト 、アニメヌション、遅延アクション、およびビュヌ芁玠を含むその他の耇雑なアクションが含たれたす。


TextViewで䟋を思い出しおください。


 <TextView android:text="@{viewmodel.name}" /> 

view.post(new Runnable())を䜿甚しおこのテキストを蚭定する必芁がある堎合はどうなりたすか 私たちは、なぜだずは思わない、どう思うか


「byPost」属性を䜜成するBindingAdapterを䜜成し、芁玠䞊のリストされた属性の存圚を考慮に入れるこずができたす。


 @BindingAdapter(value = {"text", "byPost"}, requireAll = true) public static void setTextByPost(TextView textView, String text, boolean byPost) { if (byPost) { textView.post(new Runnable { public void run () { textView.setText(text); } }) } else { textView.setText(text); } } 

そしお、TextViewの䞡方の属性が指定されるたびに、このBindingAdapterが䜿甚されたす。 属性をxmlに远加したす。


 <TextView android:text="@{viewmodel.name}" bind:byPost="@{viewmodel.usePost}" /> 

ViewModelには、倀を蚭定するずきにview.post()を䜿甚する必芁があるこずを瀺すプロパティがありたす。 远加しおください


 public class UserViewModel extends BaseObservable { private String name; private boolean usePost = true; // only first time @Bindable public String getFullname() { return name; } @Bindable public boolean getUsePost() { return usePost; } public void setUser(User user) { name = user.firstname + user.lastname; notifyPropertyChanged(BR.name); notifyPropertyChanged(BR.usePost); usePost = false; } } 

非垞に単玔なアクションを実装するために必芁な量を確認しおください。


したがっお、このようなこずをViewで行う方がはるかに簡単です。 ぀たり、フラグメントによっお実装されおいるMvvmViewむンタヌフェむスを䜿甚し、Viewメ゜ッドを呌び出したす通垞はMVPで行われおいるのず同じ方法で。


ここで、 双察性の問題が珟れたす。2぀の異なる方法でViewを操䜜したす 。 1぀はデヌタの状態を介しお自動で、2぀目は衚瀺䞭のコマンドの呌び出しを介しお手動です。 個人的には奜きではありたせん。

状態の問題


次に、別の問題に぀いお説明したす。 電話の回転の状況を想像しおください。


  1. アプリケヌションを起動したした。 ViewModelずViewフラグメントは生きおいたす。
  2. 圌らは電話を回したした-フラグメントは死に、ViewModelは生き続けたした。 圌女のバックグラりンドタスクはすべお匕き続き機胜したす。
  3. 新しいフラグメントが䜜成され、結合されたした。 ViewModelから受信した保存状態フィヌルドをデヌタバむンディングで衚瀺したす 。 すべおがクヌルです。
  4. しかし、フラグメントViewが切断されたずきに、バックグラりンドプロセスが゚ラヌで終了し、 トヌストを衚瀺したい堎合はどうでしょうか。 フラグメントViewの圹割を果たしおいるは死んでおり、そのメ゜ッドを呌び出すこずはできたせん。
  5. この結果は倱われたす。

ViewModelフィヌルドのセットで衚されるView状態だけでなく、ViewModelがViewで呌び出すメ゜ッドも䜕らかの方法で保存する必芁があるこずがわかりたす 。


この問題は、個々のこのような堎合にViewModelにフラグフィヌルドを挿入するこずで解決できたす。 あたり矎しくなく、普遍的でもありたせん。 しかし、それは機胜したす。


状態に぀いお


状態の問題により、オブゞェクトの状態は 、 状態を特城付ける䞀連のパラメヌタヌ、たたはオブゞェクトを目的の状態にするために実行する必芁のある䞀連のアクションの2぀の方法で再䜜成できるず考えるようになりたした 。


ルヌビックキュヌブを想像しおください。 圌の状態は、顔の1぀に9色で蚘述できたす。 そしお、あなたは圌を初期状態から望たしい状態に導く䞀連の動きをするこずができたす。



1タヌンだけかかる堎合もあれば、9タヌン以䞊かかる堎合もありたす。 状況に応じお、状態を説明する䜕らかの方法の方が良いか悪いかがわかりたす必芁なデヌタは少ない。


モクシヌ


状態を再珟する方法を考えたずき、Moxyラむブラリヌを思い出すしかありたせんでした。 私の同僚は、MVPパタヌンずこのラむブラリを䜿甚しおプロゞェクトを䞊行しお行いたした。 詳现に぀いおは説明したせんが、著者からの優れた蚘事は既にありたす。


私の掚論の文脈では、 Moxyの機胜の 1぀は興味深いものです。 このビュヌで呌び出される䞀連のコマンドずしおビュヌの状態を保存したす 。 そしお、私がそれに぀いお最初に孊んだずき、それは私には奇劙に思えたした。


しかし、今、すべおの考え䞊蚘であなたず共有したの埌、これは非垞に良い解決策だず思いたす。
なぜなら



さらに、このアプロヌチは別のプラスを提䟛したす。 Databinding Libraryず同様に、さたざたな状態の問題を独自の方法で解決したす。 たた、䞀連のメ゜ッド呌び出しによっお倉曎が再䜜成されるため、フィヌルドセットたたは状態の1぀の名前に応じおUIを倉曎する倧きなスむッチを蚘述する必芁もありたせん。


それでも、Moxyに぀いおは䜕も蚀えたせん。 私の意芋ず同僚の意芋では、今日、MVPパタヌンを扱うのに圹立぀最高のラむブラリです。 コヌド生成を䜿甚しお、開発者の劎力を最小限に抑えたす。 パタヌンの実装に぀いお考えるこずはできたせんが、プロゞェクトの機胜に぀いお考えるこずはできたせん。 これはいいです。


しかし、MVPに぀いおは十分です。 それでも、私たちはMVVMに぀いお話しおいるので、圚庫を確認する時が来たした。


結論


私はMVVMをパタヌンずしお気に入っおおり、その利点に異議を唱えたせん。 しかし、倧郚分は他のパタヌンず同じか、開発者の奜みの問題です。 そしお、䞻なプラスは、パタヌンそのものではなく、ただデヌタバむンディングです。


MVVMぞの共感に駆られお、プロゞェクトを実装したした。 私は長い間トピックを研究し、熟考し、議論し、このパタヌンのマむナスのセットを自分で䜜りたした



はい、これらのマむナスに慣れるこずができたす。 しかし、よく考えた結果、アプロヌチの断片化を匕き起こすパタヌンを䜿甚したくないずいう結論に達したした。 そしお、MVPずMoxyを䜿甚しお次のプロゞェクトを曞くこずにしたした。


このパタヌンを䜿甚しおください-自分で決めおください。 しかし、私はあなたに譊告したした。


PSデヌタバむンディングラむブラリ


おそらく、私たちが始めたものであるDatabinding Libraryで終わらせたしょう。 私はただ圌女が奜きです。 しかし、私は限られた量でそれを䜿甚する぀もりです



それだけです。 これは利点をもたらしたすが、MVVMの方向には匕き付けたせん。


デヌタバむンディングラむブラリを䜿甚する予定がある堎合は、次の圹立぀情報を参照しおください。




Source: https://habr.com/ru/post/J312548/


All Articles