我们在开发爱奇艺UWP客户端的过程中广泛的使用了MVVM模式,下面简单的介绍一下MVVM模式。

MVVM模式定义

MVVM包括三个核心模块:Model,View,View-Model

Model

  • Model是要处理的实际数据。

  • 但不包括处理这些数据的操作或服务。

  • 也不是用来把数据转换成某种格式来方便UI显示的。数据转换可以在ViewModel中处理,也可以定义Converter对数据进行转换。

  • 业务逻辑通常独立于Model,封装成其他类来操作Model。

  • Model是易于复用的,Model可以在多个ViewModel中使用。

  • 要保持Model的干净是具有挑战的。

例如:

  • 业务逻辑对象,如User。

  • 数据交换对象。

  • CLR元子对象,int, long, string。

  • 自动产生的实体或代理对象,例如与数据库表对应的实体类,用来解析JSON或XML等数据的实体类。

View-Model

  • View和Model的中间层,通常称为View’s Model

  • 给View提供ICommand属性。

  • 提供其他属性管理View的状态,如Button是否可见(Visibility)状态。

  • 调用其他服务获取或操作Model。

  • 聚合一个或多个Model,通过Property的方式提供给View使用。

  • 实现INotifyPropertyChanged,以满足UI绑定更新的需要。

  • 对于集合,使用ObservableCollection等

View

  • 包含主题,样式,UI布局,控件,数据绑定,事件,已经其他与用户之间的交互。
  • 避免过多的逻辑代码,这些代码尽量放入ViewModel
  • 通常View是用XAML来定义,有时可以使用少量代码。
  • 通过数据绑定或者方法调用从View Model中获取数据。
  • UI控件上的Command属性可以绑定到View Model的ICommand属性上。
  • 可以通过绑定到ViewModel的属性上对UI控件的状态进行控制。

View和View-Model的关系

  • View和View Model通过数据绑定,方法调用,属性,事件等进行关联。
  • View Model导出Model给View,也需要定义View需要的其他状态信息,如IsAllowLogin。
  • View需要管理UI Events。
  • ViewModel中的Model和属性通过双向绑定进行数据更新。

ViewModel和Model的关系

  • View Model导出Model,或者通过属性提供给View进行绑定。
  • View Model包括服务接口,配置数据接口等,以便获取View所需要的数据。

MVVM的好处

  • 开发和设计可以分开独立工作,设计师可以通过模拟数据对UI进行调试。
  • View Model和Model可以对立于View的代码进行单元测试。
  • 可以重新设计UI并重用View Model和Model的代码。
  • View Model做为View和Model之间的适配器,可以避免View的变更而需要对Model做出修改。

MVVM的性能问题

  • 避免过多的中间过渡数据,这些数据会导致过多的GC,从而影响性能。
  • 数据绑定问题,数据绑定会需要额外的动态内存分配,导致UI性能降低。使用{x:Bind}来替代Binding改善UI性能。
  • 通常把Button.Click绑定到View Model的Icommand属性上,这样会造成额外的开销。建议在后台代码使用Click Event,在事件中调用View Model的方法。
  • UI中经常把一些不展示给用户的部分的Visibility属性绑定到View Model的属性上来控制这部分UI的可见性。推荐使用x:Load或者x:DeferLoadStrategy来延迟这部分UI的加载。

Sample

下面写一个简单例子:

  • Model
   public class LoginModel : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;private void OnPropertyChanged(string name){if (PropertyChanged != null)PropertyChanged(this, new PropertyChangedEventArgs(name));}private string userName = "Tester";public string UserName{get { return userName; }set{userName = value;OnPropertyChanged(nameof(UserName));}}private string password = string.Empty;public string Passowrd{get { return password; }set{password = value;OnPropertyChanged(nameof(Passowrd));}}}- **ViewModel**-  在ViewModel中添加LoginModel的实例。-  在ViewModel中添加LoginCommand属性。```java
public class LoginViewModel : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;private LoginModel loginModel = new LoginModel();private ICommand loginCommand;public ICommand LoginCommand{get { return loginCommand; }}public LoginViewModel(){loginCommand = new LoginCommand(loginModel);}private void OnPropertyChanged(string name){if (PropertyChanged != null)PropertyChanged(this, new PropertyChangedEventArgs(name));}
}
  • Command

    • 把LoginModel传入LoginCommand,通过判断LoginModel的UserName和Password判断LoginCommand是否可执行。
public class LoginCommand : ICommand
{public event EventHandler CanExecuteChanged;private LoginModel model;public LoginCommand(LoginModel model){this.model = model;this.model.PropertyChanged += Model_PropertyChanged;}private void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){if (e.PropertyName == nameof(model.UserName) ||e.PropertyName == nameof(model.Passowrd))CanExecuteChanged?.Invoke(this, EventArgs.Empty);}public bool CanExecute(object parameter){return !string.IsNullOrEmpty(this.model.UserName) &&!string.IsNullOrEmpty(this.model.Passowrd);}public async void Execute(object parameter){MessageDialog dlg = new MessageDialog($"Login with Name:{this.model.UserName} Password:{this.model.Passowrd}", "Login");await dlg.ShowAsync();}
}
  • View.xaml

    • 通过Data Binding,把用户名和密码的数据绑定到LoginModel的UserName和Password属性上。
    • Button的Command绑定到LoginViewModel的LoginCommand属性上
<Pagex:Class="ArchitectureTutorial.MVVM.LoginPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:ArchitectureTutorial.MVVM"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><Grid Margin="24"HorizontalAlignment="Center"VerticalAlignment="Center"><Grid.RowDefinitions><RowDefinition /><RowDefinition /><RowDefinition /><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><TextBlock Text="登录"Grid.ColumnSpan="2"HorizontalAlignment="Center"Margin="12"FontSize="18" /><TextBlock Text="登录"Grid.ColumnSpan="2"HorizontalAlignment="Center"Margin="12"FontSize="18" /><TextBlock Text="密码"Margin="6"HorizontalAlignment="Right"Grid.Row="2" /><PasswordBox Grid.Row="2"Password="{x:Bind viewModel.LoginModel.Passowrd, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"Margin="6"Grid.Column="1"Width="200" /><Button x:Name="loginButton"Grid.Row="3"Grid.ColumnSpan="2"HorizontalAlignment="Center"Margin="12"Width="120"Height="32"Command="{x:Bind viewModel.LoginCommand}"CommandParameter="{x:Bind viewModel.LoginModel}"Content="登录" />    </Grid>
</Page>
  • View.cs

    • 定义LoginViewModel的实例。
public sealed partial class LoginPage : Page
{private LoginViewModel viewModel = new LoginViewModel();public LoginPage(){this.InitializeComponent();}
}

单元测试

  • 创建添加UnitTest工程
  • 每次对代码逻辑进行修改,都可以运行测试用例,检查逻辑是否有错
public void TestLogin()
{LoginViewModel viewModel = new LoginViewModel();viewModel.LoginModel.UserName = "Test";viewModel.LoginModel.Passowrd = "123";Assert.IsTrue(viewModel.LoginCommand.CanExecute(null));viewModel.LoginCommand.Execute(null);
}

参考文献

  • MVVM Best Practice
    https://www.youtube.com/watch?v=ysWK4e2Mtco

  • Model-View-ViewModel(MVVM) Explained
    https://www.codeproject.com/articles/100175/model-view-viewmodel-mvvm-explained

  • Fundamental MVVM
    https://visualstudiomagazine.com/articles/2011/08/15/fundamental-mvvm.aspx

  • MVVM Performance Tips
    https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/mvvm-performance-tips

爱奇艺Win10专业版客户端

  • 界面操作简捷,完美支持触屏设备,完美适配各种屏幕
  • 无弹窗,无后台进程
  • 支持杜比音效,杜比视界,带来更佳观影体验
  • 打开微软删掉商店搜索“爱奇艺”

MVVM - 爱奇艺UWP客户端应用与实践相关推荐

  1. 爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

    本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Andro ...

  2. Qt/qml仿制爱奇艺UWP客户端

    之前为了练习qml特意仿的爱奇艺客户端,完成了主要的框架和基本的一些控件的特效. 预览版下载地址:https://download.csdn.net/download/a18373279153/106 ...

  3. 修复计算机系统视频,电脑中出现爱奇艺视频客户端 已停止工作的修复方法

    爱奇艺是一款视频播放器,里面有海量的视频可以让我们观看,然而近日有不少用户反映说碰到这样一个问题,就是在使用的时候,突然出现爱奇艺视频客户端 已停止工作的提示,导致无法正常观看,这要怎么办呢,为此本文 ...

  4. linux系统怎么安装爱奇艺_在deepin系统下使用vek来安装爱奇艺PC客户端

    其实在deepin系统下可以通过应用商店来安装到爱奇艺,但是本文也给出了另一种方式,那就是使用vek来安装爱奇艺PC客户端.可参考深度商店应用FF Multi Converter.Imaginatio ...

  5. 【推荐实践】爱奇艺推荐中台探索与实践

    猜你喜欢 0.某视频APP推荐策略和推荐算法详解 1.如何搭建一套个性化推荐系统? 2.内容推荐策略产品经理的方法与实践 3.京东推荐算法精排技术实践 4.微博推荐算法实践与机器学习平台演进 5.腾讯 ...

  6. 爱奇艺埋点投递治理实践

    9月26日下午,爱奇艺技术产品团队举办了第19期"i技术会",本次技术会的主题是"数据治理探索与应用",来自快手.美团.快看的几位资深专家同大家就相关议题进行了 ...

  7. TiDB 在爱奇艺实时分析场景的应用实践

    作者:luzizhuo 原文来源: https://tidb.net/blog/21ab5c22 本文根据路希在[PingCAP DevCon 2021]上的演讲整理而成. 视频回顾: https:/ ...

  8. 爱奇艺PC Web NodeJS中间层实践

    爱奇艺作为中国最大的互联网视频综合门户,一直致力于给用户提供更好的使用体验及观影品质.PC主站作为爱奇艺的门户,日均覆盖用户达千万级别.随着公司业务的扩展及端上对项目更新迭代的频率越来越快,对接口的性 ...

  9. 爱奇艺推荐中台探索与实践 附下载

    爱奇艺在高速业务发展过程中出现大量业务需要提供推荐服务的场景,然而业务团队一方面没有足够的推荐领域知识,另一方面也没有足够人力去搭建一套完善的推荐系统,导致业务团队很难提升各业务内的推荐效果. 爱奇艺 ...

最新文章

  1. 境外 java 中文乱码_Java前后端交互中文出现乱码??
  2. mysql远程访问显示警告信息_mysql远程访问的时候遇到了各种问题
  3. 2013\Province_Java_A\2.振兴中华
  4. MySQL 字段约束 null, not null, default, auto_increment
  5. 事务四大特性及隔离级别
  6. c++函数的声明与定义
  7. alpha-beta剪枝算法
  8. 思岚rplidar A1激光点云数据读取
  9. Python量化投资——年化收益26%,一个大小盘轮轮动量化投资策略的回测效果
  10. AMP Roadshow技术分享路演中国专场报名
  11. HANA掀起数据处理狂潮 农夫山泉有点甜?
  12. 诗词格律[1] 诗词入门
  13. Python Turtle 画图:黑洞里的繁星(附源代码)
  14. ~3 ccf 2022-03-2 出行计划
  15. Grafana 显示某一时间点的总值
  16. DVD刻录工具(anymp4 dvd creator 7)pjb v7.2.58
  17. go语言学习第一弹:go和php的区别
  18. 云计算厂商们,你们辜负了中国的用户
  19. esxi系统重装与vsan恢复
  20. Xshel和Xftp免费版下载

热门文章

  1. 微信小程序添加删除线
  2. 【C++探索之旅】第一部分第十二课:指针一出,谁与争锋
  3. 内核aio_深入理解Java AIO(三)—— Linux中的AIO实现
  4. **IF670-Type C转DP 8K电路图
  5. linux+ldap安装目录,linux LDAP安装
  6. Matlab S-function封装学习总结
  7. Android FastBle 教程
  8. 如果美国把根域名服务器封了,中国会从网络上消失吗?
  9. jmeter+mysql+request_Jmeter之JDBC Request使用方法(oracle)
  10. 收藏 Dewplayer,一个非常简洁的flash音乐播放器