Android MVP,MVVM

一:先說MVC:原文鏈接:http://blog.csdn.net/feiduclear_up/article/details/46363207

  1. M層:適合作一些業務邏輯處理,好比數據庫存取操做,網絡操做,複雜的算法,耗時的任務等都在model層處理。
  2. V層:應用層中處理數據顯示的部分,XML佈局能夠視爲V層,顯示Model層的數據結果。
  3. C層:在Android中,Activity處理用戶交互問題,所以能夠認爲Activity是控制器,Activity讀取V視圖層的數據(eg.讀取當前EditText控件的數據),控制用戶輸入(eg.EditText控件數據的輸入),並向Model發送數據請求(eg.發起網絡請求等)。

2、再說MVP:原文鏈接:http://www.jianshu.com/p/b507a4dbe3ca

  • Presenter 中同時持有 View 以及 ModelInterface 引用,而 View 持有 Presenter 的實例。html

  • 當某個 View 須要展現某些數據時,首先會調用 Presenter 的某個接口,而後 Presenter 會調用 Model 請求數據。android

  • Model 數據加載成功後會調用 Presenter 的回調方法通知 Presenter 數據加載完畢,最後 Presenter 再調用 View 層接口展現加載後數據。算法

不太愛用mvp。mvp無非就是面向接口編程的一個典型。presenter經過view和model接口的引用,來調用具體實現類實現的方法,這麼作的好處是,業務結構清晰,且未來更換實現類超級方便,由於業務結構不用改,就只是實現類摘掉,再換一個就是。雖然明知好處,但仍是不太愛用~數據庫

最後:編程

採用哪一種軟件設計模式都是爲了達到以下目的:設計模式

易於維護網絡

易於測試架構

鬆耦合度app

複用性高ide

健壯穩定

3、MVVM:

原文鏈接:http://blog.csdn.net/johnny901114/article/details/50706329

MVVM是Model-View-ViewModel的簡寫. 它是有三個部分組成:Model、View、ViewModel。

Model:數據模型層。包含業務邏輯和校驗邏輯。

View:屏幕上顯示的UI界面(layout、views)。

ViewModel:View和Model之間的連接橋樑,處理視圖邏輯。

MVVM架構圖以下:

MMVM pattern

MVVM架構經過ViewModel隔離了UI層和業務邏輯層,下降程序的耦合度。經過DataBinding實現View和ViewModel之間的綁定。

Android App 中MVC的不足

通常來講,咱們開發Android App是基於MVC,因爲MVC的普及和快速開發的特色,一個app從0開發通常都是基於MVC的。

Activity、Fragment至關於C (Controller), 佈局至關於V(View), 數據層至關於M(Model)

鬆耦合具體帶來的好處是:

隨着業務的增加,Controller裏的代碼會愈來愈臃腫,由於它不僅要負責業務邏輯,還要控制View的展現。也就是說Activity、Fragment雜糅了Controller和View,耦合變大。並不能算做真正意義上的MVC。

編寫代碼基本的過程是這樣的,在Activity、Fragment中初始化Views,而後拉取數據,成功後把數據填充到View裏。

假若有以下場景

咱們基於MVC開發完初版本,而後企業須要迭代2.0版本,而且UI界面變化比較大,業務變更較小,怎麼辦呢? 
當2.0的全部東西都已經評審事後。這個時候,新建佈局,而後開始按照新的效果圖,進行UI佈局。而後還要新建Activity、Fragment把相關邏輯和數據填充到新的View上。 
若是業務邏輯比較複雜,須要從Activity、Fragment中提取上個版本的全部邏輯,這個時候本身可能就要暈倒了,由於一個複雜的業務,一個Activity幾千行代碼也是很常見的。千辛萬苦作完提取完,可能還會出現不少bug。

MVP架構圖以下:

這裏寫圖片描述

MVP把視圖層抽象到View接口,邏輯層抽象到Presenter接口,提到了代碼的可讀性。下降了視圖邏輯和業務邏輯的耦合。

可是有MVP的不足:

  1. 接口過多,必定程度影響了編碼效率。其實這也不算是不足,爲了更好的分層解耦,這也是必須的。
  2. 致使Presenter的代碼量過大。

這個時候MVVM就閃亮登場了。從上面的MVVM功能圖咱們知道:

  1. 可重用性。你能夠把一些視圖邏輯放在一個ViewModel裏面,讓不少view重用這段視圖邏輯。 
    在Android中,佈局裏能夠進行一個視圖邏輯,而且Model發生變化,View也隨着發生變化。
  2. 低耦合。之前Activity、Fragment中須要把數據填充到View,還要進行一些視圖邏輯。如今這些均可在佈局中完成(具體代碼請看後面) 
    甚至都不須要再Activity、Fragment去findViewById。這時候Activity、Fragment只須要作好的邏輯處理就能夠了。

如今咱們回到上面從app1.0到app2.0迭代的問題,若是用MVVM去實現那就比較簡單,這個時候不須要動Activity、Fragment, 
只須要把佈局按照2.0版本的效果實現一遍便可。由於視圖邏輯和數據填充已經在佈局裏了,這就是上面提到的可重用性。

4.1. The view

A view component in MVP contains a visual part of the application.

The view binds to observable variables and actions exposed by the view model typically using the data binding framework.

The view is responsible for handling for example:

  • Menus

  • Permissions

  • Event listeners

  • Showing dialogs, Toasts, Snackbars

  • Working with Android View and Widget

  • Starting activities

  • All functionality which is related to the Android Context

4.2. The view model

The view model contains the data required for the view. It is an abstraction of the view and exposes public properties and commands. It uses observable data to notify the view about changes. It also allows to pass events to the model. It is also a value converter from the raw model data to presentation-friendly properties)

The view model has the following responsibilities:

  • Exposing data

  • Exposing state (progress, offline, empty, error, etc)

  • Handling visibility

  • Input validation

  • Executing calls to the model

  • Executing methods in the view

The view model should only know about the application context. the application context can:

  • Start a service

  • Bind to a service

  • Send a broadcast

  • Register a broadcast receiver

  • Load resource values

It cannot:

  • Show a dialog

  • Start an activity

  • Inflate a layout

4.3. The model

Contains a data provider and the code to fetch and update the data. The data can be retrieved from different sources, for example:

  • REST API

  • Realm db

  • SQLite db

  • Handles broadcast

  • Shared Preferences

  • Firebase

  • etc.

Basically the same as the model in the MVP.

4、MVVM BroadcastReceiver

I have a class WifiManager that holds a Boolean value that represents either wifi connected or wifi disconnected.

the Boolean field gets updated with a broadcastReceiver I have in that class.

private BroadcastReceiver wifiScanReceiver;

private boolean isWifiConnected = false;

wifiScanReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context c, Intent intent) {
                    // Wifi connected/disconnected
                    NetworkInfo nwInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
                    final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
                    if (nwInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                        // wifi connect
                        isWifiConnected = true;
                    } else {
                        // wifi disconnected
                        isWifiConnected = false;
                    }
                }
        };

        context.registerReceiver(wifiScanReceiver, wifiIntentFilter);

In my MainActivity I have a WifiManager field, and what I want is to do data binding that will change one of the menu items based on the Boolean value -> if isWifiConnected=false set icon to @drawalbe/xxx, if isWifiConnected=true set icon to @drawalbe/yyy.

Meaning - having sort of a "listener" to changes of the isWifiConnected value, and based on that - set one of the MenuItem's icon to either @drawalbe/xxx or @drawalbe/yyy.

I know there are tons of ways to do it, from broadcasting an Intent in the BroadcastReceiver and catch it in the MainActivity to just have a Handler running and checking the isWifiConnectedevery 3 seconds..

What I am really looking for is sort of data binding with a converter, like you would do in a MVVM project.

Is there such a thing in android?

1 Answer

 

I assume you know about android data binding and you're just asking how to do it for this specific case. If not, here is the android data binding guide.

You will need a way to observe the boolean value so the UI can remain updated. The easiest way is to make it an ObservableBoolean field of your model object:

public class ViewModel {
    public final ObservableBoolean isWifiConnected = new ObservableBoolean();
    // other things you want to bind to your layout...
}

When you create the binding, you must also assign the model:

public void onCreate(Bundle icicle) {
    ActivityMainBinding binding =
        DataBindingUtil.setContentView(this, R.layout.activity_main);
    this.model = new ViewModel();
    binding.setModel(this.model);
}

And when you receive the broadcast, you update the model:

wifiScanReceiver = new BroadcastReceiver() {
        //...
        model.isWifiConnected.set(newValue);
        //...
    };

And your layout would be something like this:

<layout ...>
    <data>
        <variable name="model" type="com.example.ViewModel"/>
    </data>
    <!-- rest of layout -->
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@{model.isWifiConnected ? @drawable/xxx : @drawable/yyy}"/>
</layout>

You could also avoid the model class if you keep track of the binding and set the variable directly on it. In that case, you'd have a variable:

<variable name="isWifiConnected" type="boolean"/>

And your broadcast receiver would set the value:

binding.setIsWifiConnected(newValue);
相關文章
相關標籤/搜索