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);
相关文章
相关标签/搜索