美文网首页
(1)MVVM初见

(1)MVVM初见

作者: 雨落川川 | 来源:发表于2020-10-28 16:02 被阅读0次

MVVM架构模式已经非常火了,我还是只知其一不知其二,搜了很多帖子学习,这里整理一下学习笔记。

a.便于理解,先把一些字面意思放在这里:
Model 模型(数据层)

是应用程序中处理程序数据逻辑的部分,通常负责从本地数据库存取,远程存取数据。

View 视图(UI显示)

是应用程序中处理数据显示的部分,通常视图都是依据模型来创建的。

Controller 控制者,管理者,调度员

在应用程序中处理用户交互的部分,通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

Presenter 主持人
ViewModel 视图模型
Repository 仓库,存放处
1.MVC

MVC的模式优点在于分离UI与业务职责,增加可测试性与可扩展性,但缺点是,View即依赖于Controller又依赖于Model,在修改UI内容时,也需要修改对应的Model,降低架构的灵活性,View和Model的职责存在部分重叠,耦合度高,实际操作中很难按照MVC模式严格去分离。

2.MVP

Model-View-Presenter ;MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
MVP模式的优点是模型与视图完全分离,我们可以修改视图而不影响模型,因为在这个模式下,所有的交互都发生在Presenter内部,也利于脱离用户接口来测试业务逻辑。缺点是会导致视图和Presenter的交互过于频分,Presenter与具体的View没有直接关联,而是通过定义好的接口进行交互,这会导致有大量的接口生成,造成代码繁具,很难维护,这也是很多像我一样从入坑到放弃这种模式的原因。

3.MVVM

MVP的特质是“依赖倒置”,MVVM的特质是“数据驱动”。
学这个的目的,是因为这句话,显然说明二者并没有谁演化自谁的关系了,JetPack MVVM是MVVM模式在Android开发中的具体落实,“数据驱动”这个理解有点难,看帖子不理解就找个教程写个Demo理解一下,B站是个学习网站,很多优质UP主提供了帮助,这里贴一下一个小Demo:


篮球比赛计分器

一个计分器,点击加分向对应的队加相应的分数,点击回退取消上一步的操作,点击重置将两队的比分清零。
首先定义MyViewModel,继承自ViewModel,在这里我们定义数据,并处理逻辑。

public class MyViewModel extends ViewModel {
    // 定义两队的分数
    // MutableLiveData可修改的LiveData,因为分数需要变化,LiveData
    private MutableLiveData<Integer> aTeamScore;
    private MutableLiveData<Integer> bTeamScore;
    //缓存两队当前分数,用于回退一步
    private int aBack, bBack;

    public MutableLiveData<Integer> getATeamScore() {
        if (aTeamScore == null) {
            aTeamScore = new MutableLiveData<>();
            aTeamScore.setValue(0);
        }
        return aTeamScore;
    }

    public MutableLiveData<Integer> getBTeamScore() {
        if (bTeamScore == null) {
            bTeamScore = new MutableLiveData<>();
            bTeamScore.setValue(0);
        }
        return bTeamScore;
    }

    /**
     * 给A队加分,在添加之前保留A、B两队的分数,用于在执行undo操作时使用
     * @param p 要加的分数
     */
    public void aTeamAdd(int p) {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        aTeamScore.setValue(aTeamScore.getValue() + p);
    }

    public void bTeamAdd(int p) {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        bTeamScore.setValue(bTeamScore.getValue() + p);
    }

    /**
     * 清零
     */
    public void reset() {
        aBack = aTeamScore.getValue();
        bBack = bTeamScore.getValue();
        aTeamScore.setValue(0);
        bTeamScore.setValue(0);
    }

    public void undo() {
        aTeamScore.setValue(aBack);
        bTeamScore.setValue(bBack);
    }
}

布局文件的内容除了常规控件的内容,也就是使用了JetPack提供的DataBinding,篇幅有限这里仅仅对新生事物粘贴一下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="data"
            type="com.nxhope.community.state.MyViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.BasketballScoring">

      <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:text="@{String.valueOf(data.getATeamScore())}"
            android:textColor="#E91E63"
            android:textSize="80sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline10"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline9"
            tools:text="120" />

     <Button
            style="@style/button_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:onClick="@{()->data.aTeamAdd(1)}"
            android:text="+1"
            app:layout_constraintBottom_toTopOf="@+id/guideline11"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline10" />

    <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="60dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            android:onClick="@{()->data.undo()}"
            app:layout_constraintBottom_toTopOf="@+id/guideline14"
            app:layout_constraintEnd_toStartOf="@+id/guideline7"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline13"
            app:srcCompat="@drawable/ic_baseline_undo_24" />

   </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

布局文件转换为data-bingding layout这步可以不用手写,windows用户选中布局的根节点alt+enter就会提示出一个选项“convert to data binding layout" 的内容, 转换后会多出来<data>节点中的内容,我们只需要name中命名,在type中导入我们定义好的ViewModel即可。

剩下的事情就是为控件绑定ViewModel提供的数据或者操作了,TextView中
android:text="@{String.valueOf(data.getATeamScore())}"为A队分数显示区域绑定数据,Button中
android:onClick="@{()->data.aTeamAdd(1)}"绑定了为A队加1的操作,当然加2加3就类似了,ImageButton绑定了我们在ViewModel中定义的undo()操作,也就是回退一步。可以看到,到目前为止,我们好像只关心了布局文件和ViewModel的内容,对于页面Activity反而还没下手,不像常规操作,之所以这样,是因为Activiy中真的没啥可处理了,看代码:

public class BasketballScoring extends AppCompatActivity {
    private MyViewModel viewModel;
    private ActivityBasketballScoringBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //DataBinding
        binding = DataBindingUtil.setContentView(this, R.layout.activity_basketball_scoring);
        //ViewModel
        viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
        binding.setData(viewModel);
        binding.setLifecycleOwner(this);
    }
}

Activity中我们只是做了将布局和ViewModel绑定,当然这里还写了一些LiveData和Lifecycle的内容(我还没研究透彻,这里按下不表,听下回分说),不是重点,重点是,Activity中太简洁了,常见的FindViewById( ),setOnclickListener( ),setText( )统统不见踪影,以及我们可能要定义的常量,Bean什么的也没了,这就很香了。
玩玩这个Demo,比如删除布局文件中的一些内容,常规方式可能就会出现空指针,控件找不到造成的Crash,但现在不会了,MVVM模式用于解决“视图调用一致性问题”这句话也诚不欺我,这时候再拿出KunMinX大佬的图:



再品品,想总结些内容,品出来的是:“我是小白,特别的白”、
帖子前面提到了Repository ,这里面并没有说,本着的是不懂就不装懂的原则,况且程序员有的东西懂了怎么用,不一定会表达,继续学习,Android推出的JetPack内容是时候学学了:


Jetpack

相关文章

  • (1)MVVM初见

    MVVM架构模式已经非常火了,我还是只知其一不知其二,搜了很多帖子学习,这里整理一下学习笔记。 a.便于理解,先把...

  • MVVM初见

    _翻译自 _:Introduction to MVVM(注:没有完全翻译全文,只是翻译了和MVVM真正相关的部分)...

  • 值得学习的技术文章(持续添加)

    1. MVVM 学习资料 MVVM奇葩说 面向协议的 MVVM 架构介绍 MVVM With ReactiveCo...

  • android 安卓 mvp mvvm - mvvm

    android 安卓 mvp mvvm - mvpandroid 安卓 mvp mvvm - mvvm 1.MVV...

  • Android MVVM 解读 3. Android MVVM

    Android MVVM 解读 3. Android MVVM 介绍(1) 包含的信息 Android MVVM ...

  • 3.mvc和mvvm的区别和使用

    1.mvc和mvvm的由来 2.mvvm的概念 3.mvc和mvvm的区别 4.MVVM的实践 1.model层的...

  • Vue之MVVM模式和第一个Vue程序

    一、MVVM模式和第一个Vue程序 目录:MVVM模式、第一个Vue程序 1.MVVM模式 1)什么是MVVM?M...

  • 初识Vue

    1. MVVM模式 Vue采用MVVM(Model-View-ViewModel)模式实现,MVVM模式由MVC演...

  • Xamarin.Forms MVVM

    目录 - Xamarin.Forms 前言 本文介绍MVVM:一、MVVM简介二、MVVM示例 环境 1.Visu...

  • vue的ms题目

    1、什么是 mvvm? MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。...

网友评论

      本文标题:(1)MVVM初见

      本文链接:https://www.haomeiwen.com/subject/xzpqvktx.html