ViewModel、LiveData、DataBinding

ViewModel

ViewModel的引入

如果系统销毁或重新创建界面控制器,则存储在其中的任何临时性界面相关数据都会丢失。例如,应用的某个 Activity 中可能包含用户列表。因配置更改而重新创建 Activity 后,新 Activity 必须重新提取用户列表。对于简单的数据,Activity 可以使用 onSaveInstanceState() 方法从 onCreate() 中的捆绑包恢复其数据,但此方法仅适合可以序列化再反序列化的少量数据,而不适合数量可能较大的数据,如用户列表或位图。
架构组件为界面控制器提供了 ViewModel 辅助程序类,该类负责为界面准备数据。在配置更改期间会自动保留 ViewModel 对象,以便它们存储的数据立即可供下一个 Activity 或 Fragment 实例使用。

实现ViewModel

package com.zyb.viewmodeltest;

import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    public int num = 0;
}

从 Activity 访问该列表,如下所示:

package com.zyb.viewmodeltest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.lifecycle.ViewModelProviders;
public class MainActivity extends AppCompatActivity {

    MyViewModel myViewModel;
    Button button1,button2;
    TextView showScore;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        button1 = findViewById(R.id.button);
        button2 = findViewById(R.id.button2);
        showScore = findViewById(R.id.textView);

        showScore.setText(myViewModel.num+"");

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myViewModel.num++;
                showScore.setText(myViewModel.num+"");
            }
        });

        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myViewModel.num += 2;
                showScore.setText(myViewModel.num+"");
            }
        });

    }
}

ui:

功能:点击+1,数字+1,点击+2,数字在原来基础上+2
优点:不用我们保存之前加过数字的状态,因为在配置更改期间会自动保留 ViewModel 对象
缺点: showScore.setText();出现过多,代码累赘,setOnClickListener出现过多代码不好看

LiveData

使用 LiveData 具有以下优势:

确保界面符合数据状态
LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。观察者可以在每次发生更改时更新界面,而不是在每次应用数据发生更改时更新界面。
不会发生内存泄露
观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
不会因 Activity 停止而导致崩溃
如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
数据始终保持最新状态
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
适当的配置更改
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
共享资源
您可以使用单一实例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。有关详情,请参阅扩展 LiveData。
实现LiveData

package com.zyb.livedatatest;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private MutableLiveData<Integer> num;

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

    public MutableLiveData<Integer> addNum(int n){
        num.setValue(num.getValue()+n);
        return num;
    }
}

从 Activity 访问该列表,如下所示:

package com.zyb.livedatatest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProviders;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    ImageButton redButton,blueButton;
    TextView score;
    MyViewModel myViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        redButton = findViewById(R.id.imageButton);
        blueButton = findViewById(R.id.imageButton3);
        score = findViewById(R.id.textView);

       myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
       //观察数据是否改变,改变就重写
       myViewModel.getNum().observe(this, new Observer<Integer>() {
           @Override
           public void onChanged(Integer integer) {
               score.setText(integer+"");
           }
       });
       redButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               myViewModel.addNum(1);
           }
       });
       blueButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               myViewModel.addNum(-1);
           }
       });
    }
}

ui:

功能:左边+1,右边-1
优点:将setText()减少到一句
缺点:setOnClickListener出现过多代码不好看

DataBinding

在buid.gradle开启数据绑定:

之后重新构建项目sync
进入activity_main.xml中点击

之后会多两个标签和

package com.zyb.databindingtest;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    MutableLiveData<Integer> cnt;

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

    public void add(int n){
        cnt.setValue(cnt.getValue()+n);
    }
}

MainActivity.java

package com.zyb.databindingtest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;

import android.os.Bundle;

import com.zyb.databindingtest.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    //绑定1:将界面对象绑定到控制器的ActivityMainBinding对象中(可以调用bind.xml标签名)
    ActivityMainBinding bind;//注意这个类的名字和你Java文件的名字相同,不是固定的
    MyViewModel myViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bind = DataBindingUtil.setContentView(this,R.layout.activity_main);
        myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        //绑定2:将屏幕数据和控件的xml绑定
        bind.setData1(myViewModel);//setData1是因为在xml那个数据的name自己设定的data1,所以这setData1也是不固定的
        //这句很重要,相当于之前设置的观察者语句
        bind.setLifecycleOwner(this);

    }
}

ui:

功能:显示点击按钮次数
优点:控制器代码减少,分工更明确
activity_main.xml变化:这个写法有点像javaweb的模板引擎thymeleaf



最后的
thymeleaf相关图:

相关变化图:
最原始的,通过findViewById将单个组件的引用和控制器来连接起来,数据显示和变化都在控制器中

加入ViewModel之后将页面数据(UIData)单独提出来封装

加入LiveData,将之前提出来的UIData换为LiveData类型的,因为它满足观察者类型,可以减少setText的书写,降低代码耦合性

加入DataBinding将数据操作绑定到相关界面的xml文件中,减少控制器的代码量,分工更明确了
ui

参考链接

android开发者官网
视频

原文地址:https://www.cnblogs.com/cstdio1/p/12346617.html

时间: 2025-01-14 00:33:07

ViewModel、LiveData、DataBinding的相关文章

利刃 MVVMLight 2:Model、View、ViewModel结构以及全局视图模型注入器的说明

上一篇我们已经介绍了如何使用NuGet把MVVMLight应用到我们的WPF项目中.这篇我们来了解下一个基本的MVVMLight框架所必须的结构和运行模式. MVVMLight安装之后,我们可以看到简易的框架布局,如上篇,生成了一个ViewModel文件夹,ViewModel层的内容都放在这边,除了Main对象的ViewModel之外,还包含一个ViewModelLocator文件, 用来注入当前的ViewModel全局实例. 一.先来说说分层结构: 如图: 1.View负责前端展示,与View

MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js 概念摘录

转自:http://www.cnblogs.com/xishuai/p/mvc-mvp-mvvm-angularjs-knockoutjs-backbonejs-reactjs-emberjs-avalonjs.html MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是将 M 和 V 的实现代码分离,从而使同一个程序可以使用不同的表现形式. 交互方式(所有通信都是单向的): View 传送指令到 Contro

web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史

秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知,不问自晓,古今行事,未之有也 」 我们都知道如今流行的框架:Vue.Js.AngularJs.ReactJs.已经逐渐应用到各个项目和实际应用中,它们都是MVVM数据驱动框架系列的一种. 在了解MVVM之前,我们先回想一下前端发展的历史阶段,做到心中有数,才会更好理解. 这段回想历史.由于网上就可查不少资料,

MVC、MVP、MVVM模式对比总结(2)横向构架模型

前言说明 在实战项目及学习中来总结一下Android端项目构架 包括MVC.MVP.MVVM,主要针对移动Android端 该篇只描述横向构架模型 目录 1.构架基础 2.横向构架模型 3.纵向构架流程 4.代码例子 2.横向构架模型 MVC构架 综合说明: 以manager作为controller层 activity/fragment(view)调用manager(controller)处理请求 manager(controller)调用NetHelp(model)处理业务逻辑 虚线代表返回结

[转]MVC、MVP、MVVM

界面之下:还原真实的 MVC.MVP.MVVM 模式 [日期:2015-10-28] 来源:github.com/livoras  作者:戴嘉华 [字体:大 中 小] 前言 做客户端开发.前端开发对MVC.MVP.MVVM这些名词不了解也应该大致听过,都是为了解决图形界面应用程序复杂性管理问题而产生的应用架构模 式.网上很多文章关于这方面的讨论比较杂乱,各种MV*模式之间的区别分不清,甚至有些描述都是错误的.本文追根溯源,从最经典的Smalltalk- 80 MVC模式开始逐步还原图形界面之下最

MVC、MVP、MVVM 模式(待续)

本文将从收集来的资料整理分析MVC模型的各种应用以及其演化历程 一. 介绍 MV* 模式 MVC.MVP.MVVM 模式都是为了解决图形界面应用程序复杂性管理问题而产生的应用架构模式.追根溯源,从最经典的Smalltalk-80 MVC模式开始逐步还原图形界面之下最真实的MV*模式. GUI程序所面临的问题 图形界面的应用程序提供给用户可视化的操作界面,这个界面提供给数据和信息.用户输入行为(键盘,鼠标等)会执行一些业务逻辑,可能会导致对应用程序数据的变更,数据的变更自然需要用户界面的同步变更以

【框架篇】mvc、mvp、mvvm使用关系总结

MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑.MVC被独特的发展起来用于映射传统的输入.处理和输出功能在一个逻辑的图形化用户界面的结构中. 数据关系 View 接受用户交互请求 View 将请求转交给Controller Controller

【转】对MVC、MVP、MVVM的懂得

[转]对MVC.MVP.MVVM的懂得 转载地址:http://www.myexception.cn/vc-mfc/1612241.html 对MVC.MVP.MVVM的理解 最近看了一堆js框架的文档,有点乱,想分门别类整理一下,但是首先需要搞清楚这些框架里面经常谈论的MV*之类的概念.MVC的概念很早就知道,现在发现还有MVP.MVVM,那么这些设计模式有什么区别呢?谈一下自己的理解. 刚开始理解这些概念的时候认为这几种模式虽然都是要将view和model解耦,但是非此即彼,没有关系,一个应

Silverlight项目笔记1:UI控件与布局、MVVM、数据绑定、await/async、Linq查询、WCF RIA Services、序列化、委托与事件

最近从技术支持转到开发岗,做Silverlight部分的开发,用的Prism+MVVM,框架由同事搭好,目前做的主要是功能实现,用到了一些东西,侧重于如何使用,总结如下:   1.UI控件与布局     2.MVVM     3.数据绑定     4.await/async     5.Linq查询     6.WCF RIA Services     7.序列化     8.委托与事件 1.UI控件与布局 常用的主要是Grid.StackPanel.Border,其中最常用的的是Grid,是一