Androidアーキテクチャ設計---MVVMモデルについての検討

13214 ワード

###一、MVPモードのメリットとデメリット
MVVMについて話す前に、MVPの階層を簡単に振り返ってみると、MVPは全部で3つの階層に分かれています.
  • a、View:xmlファイルとActivity/fragmentに対応するビューレイヤ;
  • b、Presenter:論理制御層、同時にViewとModelオブジェクトを持つ;
  • c、Model:エンティティ層で、エンティティデータの取得を担当します.

  • MVPモードシーケンス図
    MVPモードには大きなメリットがあります
  • 1.解結合、ビジネスロジック、ビュー分離;
  • 2.プロジェクトコード構造(フォルダ)が明確で、見ただけで何をしているかがわかります.
  • 3.ユニットテストを容易にする(実際には第一点である);
  • 4.協同作業(例えば、デザイナーが図を出さない前にビジネスロジックコードを書いたり、他の人がコードを引き継いだりするのが容易です);
  • しかし、米中が不足している部分もあり、MVPモードの欠点は以下の通りです.
  • 1.Presente層とView層はインタフェースを介して相互作用し,インタフェースの粒度は制御しにくい.粒度が小さすぎると、大量のインタフェースが存在し、コードが砕けすぎてしまう.粒度が大きすぎて、デカップリング効果がよくありません.ビュー定義のメソッドは必ずしもすべて使用する必要はありませんので、後で先に定義する必要があるだけかもしれません(後で削除するかどうかは不明ですが)、後にいくつかのメソッドが削除される場合は、PresenterとActivityが削除され、面倒です.
  • 2.V層とP層はまだ一定の結合度を持っている.V層のUI要素が変更されると、対応するインタフェースが変更され、データがUIにどのようにマッピングされるか、イベントリスニングインタフェースが変更され、全身を動かす必要があります.この層もデカップリングできればもっとよかったのに.
  • 3.複雑な業務は同時にP層が大きすぎる可能性があり、コードの肥大化の問題は依然として解決できない.これはもうインタフェースの粒度制御の問題ではない.業務論理がますます多くなると、View定義の方法がますます多くなり、ActivityとFragmentの実現方法がますます多くなり、依然として肥大化する.

  • ###二、MVVMモード
    ###2.1、データの双方向バインドOK、今からMVVMを紹介します.MVVMモードは4層ではなく、MVPと同じ3層ですが、MVVMがMVPのアップグレード版であることに同意しません.両者は同じところがありますが、MVPのいくつかの利点は、MVVMも取って代わることができません.MVVMの3層モデルは以下の通りです.
    Model:MVPのようなデータ実装と論理処理を担当します.View:ActivityとXMLに対応し、MVPのようにViewの描画とユーザーとのインタラクションを担当します.ViewModel:関連付けを作成し、modelとviewをバインドします.その後、モデルの変更はviewmodelを介してviewにフィードバックされます.(viewのxmlレイアウトファイルは、特定の作成を経て、コンパイルツールが処理すると、生成されたコードがview modelのデータ通知メッセージを受信し、インタフェースを自動的にリフレッシュします).
    MVVMモードの最大のハイライトは双方向バインドであることがわかります
    一方的なバインドでは、データの流れは一方的で、コードからUIにしか流れません.双方向バインドされたデータの流れは双方向であり、ビジネスコードのデータが変更されると、UI上のデータがリフレッシュされる.ユーザがUIを介してデータをインタラクティブに編集すると、データの変化はビジネスコードのデータに自動的に更新される.双方向バインディングでは、DataBindingを使用することができます.DataBindingはデータとUIバインディングを実現するフレームワークであり、MVVMモードを構築する重要なツールです.そのためAndroidではMVVMを実現するのが便利になり、IOSではblockコールバックやreactiveCocoaライブラリも使用されます.
    #####2.2、DataBinding基本用法
    #####-Gradle構成
    Gradleのandroidドメイン内でdataBindingを開くだけでOKです.
    #####-エンティティークラスの作成
    public class User {
        private String name;
        private String age;
    
        public void onItemClick(View pView) {
            Toast.makeText(pView.getContext(), getName(), Toast.LENGTH_SHORT).show();
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public User(String name, String age) {
            this.name = name;
            this.age = age;
        }
    }

    バインドを実現すると、レイアウトの作成は従来のxmlとは異なります
    activity_main.xml
    
    "1.0" encoding="utf-8"?>
    
        
            
        
        
            
        
    

    DataBindingを使用すると、レイアウトはすべてラベルをルートノードとして使用します.このレイアウトは最終的にBindingクラスを生成します.命名規則は、単語の頭文字が大文字で、下線を削除し、最後にBindingを追加します.ここはactivityですmain.xmlなので、Activity MainBindingが生成されます.
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //setContentView(R.layout.activity_main);
            ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
            User user = new User("Looperjing", "20");
            viewDataBinding.setUser(user);
        }
    }

    setContentView(R.layout.activity_main)をDataBindingUtil.setContentView(this,R.layout.activity_main)に置き換え、生成されたバインディングクラスActivity MainBindingを返し、userをバインディングします.運転効果は以下の通りです.
    しかし、これはまだ双方向バインドを実現することはできません.双方向バインドを実現するには.エンティティクラスを変更する必要があります.
    
    public class User extends BaseObservable {
    
        public ObservableField<String> name = new ObservableField<>();
    
        public ObservableField<String> age = new ObservableField<>();
    
    
        public User(String pName, String pAge) {
            name.set(pName);
            age.set(pAge);
        }
    
        @Bindable
        public String getName() {
            return name.get();
        }
    
        public void setName(String name) {
            this.name.set(name);
            notifyPropertyChanged(mvvm.wangjing.com.mvvm.BR.name);
        }
    
        @Bindable
        public String getAge() {
            return age.get();
        }
    
        public void setAge(String age) {
            this.age.set(age);
        }
    
        public void onItemClick(View pView) {
            Toast.makeText(pView.getContext(), name.get(), Toast.LENGTH_SHORT).show();
            setName("June");
        }
    
    }

    public ObservableField name=new ObservableField<>()という方法で属性を作成します.ObservableFieldは、エンティティークラスの値が変更されると自動的にViewリフレッシュを通知する役割を果たします.名前を使う.get()は属性値を取得し、name.set()属性値を設定します.フィールドを変更するには、そのフィールドのgetメソッドに@Bindable注記を追加し、そのフィールドのsetメソッドにnotifyPropertyChanged(mvm.wangjing.com.mvvm.BR.name)を追加する必要があります.上のコードは、Viewをクリックしたときにnameの値を変更することを示しています.dadabindingのもっと高級な使い方について:私を突き刺します.
    ObservableFieldの場合、これらのフィールドは少し分類して包むことができます.たとえば、一部のフィールドはコントロールのStyleプロパティにバインドされている可能性があります.(長さ、色、サイズなど)このようなView Styleに対するフィールドに対して、View Styleクラスがラップされていることを宣言することで、コードロジック全体がより明確になり、読み取りが悪くなります.他のフィールド、例えばtitle、imageUrl、nameなどのデータソースタイプに属するフィールドについては、データフィールドとも呼ばれ、ビジネスデータとパトロールです.これらのフィールドは1つに置くことができます.
    MVVMモードを実装する中でViewModelの重要な部分であるDataBindingがどのように双方向にバインドされているかを示した.
    2.2、AndroidのMVVMモード
    ###a、View層view層はxmlとActivity
    "1.0" encoding="utf-8"?>
    
        
            
        
        
            
        
    

    今回導入されたのは、MVVMのVMレイヤであるUserViewModelであり、Modelの業務データが変化した場合、UIの更新、UIの更新を通知した場合、Modelに変化を通知する.
      
            <variable
                name="model"
                type="mvvm.wangjing.com.mvvm.User.UserViewModel" />
        data>
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            final ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
            UserViewModel userViewModel=new UserViewModel(this,viewDataBinding);
        }
    }

    我々はXML,Activity,FragmentのみでView層のコードを書き,View層は業務に関することをしない,つまりActivityでは業務ロジックや業務データに関するコードを書かず,UIを更新することはデータバインドによって実現され,できるだけView Modelで行うことが分かった.
    ####b、ViewModel層
    
    public class UserViewModel {
    
        //  ,        public,          
    
        public User user;
    
        public ActivityMainBinding mainBinding;
    
        public Activity activity;
    
    
        public UserViewModel(Activity pActivity, ActivityMainBinding pMainBinding) {
            this.activity = pActivity;
            this.mainBinding = pMainBinding;
            mainBinding.setModel(this);
            init();
        }
    
        private void init() {
           user=new User("LooperJing","20");
        }
    
        public void onItemClick(View pView) {
            Toast.makeText(pView.getContext(), "  Medel ,    ,      ", Toast.LENGTH_SHORT).show();
        }
    }

    ViewModelは業務の論理処理に専念し、業務論理と業務データに関することだけをし、UIに関することはここに書かないでください.ViewModel層はコントロールの参照を一切持たず、ViewModelではUIコントロールの参照を通じてUIを更新することはありません.ただし、ViewModelはデータを変更する可能性があります.データとUIがバインドされているため、対応するコントロールでUIが自動的に更新されます.
    ####c、Model層
    Model層は職責データ取得であり、ネットワーク要求の論理はここに書かれており、MVPに似ている.そのため、ViewModelレイヤはModelの参照を持って、Modelにデータの取得を通知することができると思います.同時に、Modelはデータの取得後、コールバックしてViewModelにデータの変更を通知し、UIを更新します.
    まとめてみると、ViewレイヤのActivityはDataBindingによってBindingインスタンスを生成し、このインスタンスをView Modelに渡し、View Modelレイヤは自身をBindingインスタンスにバインドすることで、ViewにおけるlayoutとView Modelの双方向バインドを実現する.ビューモデルを導入しないと、1つのxmlに複数のデータオブジェクトが含まれる可能性があるという欠点もあります.この複数のデータオブジェクトを導入するだけで、xmlレイアウトの鮮明さが低下します.この方法では、layoutファイルのdataラベルにビューモデルを導入するだけでいいのです.他のデータオブジェクトは、ViewModelで一括処理されます.3つのコラボレーションについては、次の図に示します.
    from Kelin
    ###d、MVVMの問題第一点:データバインディングによりBugをデバッグすることが困難になる.インタフェースが異常になっているのを見て、あなたのViewのコードにBugがあるかもしれないし、Modelのコードに問題があるかもしれません.データバインディングにより、1つの位置のBugが他の位置に迅速に伝達され、元の問題の場所を特定するのは容易ではありません.2つ目:大きなプロジェクトでは、データバインドにより多くのメモリが必要です.MVVMの理解について、ネット上で、みんなの全体的な理解はあまり悪くないことを発見して、しかし細部の上でいくつかの異なる地方があって、例えばMVVMの業務の論理の分業はあまり明確ではありませんて、一部の人はView Modelで書くことができて、ある人はMoldelの中で書くことができて、甚だしきに至ってはいくつかの反対派が私を突いて、MVVMが背いていると思っているJAVAの階層設計の思想、***
    Please accept mybest wishes for your happiness and success !
    推荐阅读:Androidアーキテクチャー设计---MVPモード第(一)篇之基本认実Androidアーキテクチャー设计---MVPモード第(二)篇,如何减少类爆炸
    参照先:
    tech.meituan.com/android_mvv…
    www.jianshu.com/p/2fc41a310…
    zhuanlan.zhihu.com/p/23772285?…
    github.com/tianzhijiex…
    www.open-open.com/lib/view/op…
    juejin.im/entry/57d16…
    github.com/Kelin-Hong/…