Mvvmcross Platform 入门






4.33/5 (7投票s)
在本文中,我将对 mvvmcross 平台的基本概念进行简要概述。我们将探讨 mvvmcross 项目架构和一些 mvvmcross 类。
引言
Mvvmcross 是一个 MVVM
平台,可以解决你在开发跨平台(如 Android、Windows Phone 或 IOS)时迟早会遇到的许多问题。
问题在于,每个平台都有自己的规范,因此你无法简单地编写一个代码并在多个平台上运行。这时 Xamarin 就变得非常方便了。
mvvmcross 的主要特点是,你不仅将逻辑与视图分离(如 MVVM
和 MVC
模式),还将其与特定平台实现分离。
你的业务逻辑将在 PCL(可移植类库)中实现,每个平台都可以将其作为自己的逻辑来引用,同时相应地实现其原生端。
查看 mvvmcross manifest
https://github.com/MvvmCross/MvvmCross/wiki/The-MvvmCross-Manifesto
Mvvmcross 在 Github 上
https://github.com/MvvmCross/MvvmCross
*在此特定示例中,我将展示 mvvmcross 在 Windows 8.1 应用商店应用上的实现。
MVVM 模式
熟悉 MVC
模式的人会发现它与 MVVM
相似,因为它旨在解决相同的问题,但方式略有不同。
而 MVC
将程序分为三个模块:视图、控制器和模型,MVVM
则通过匹配视图与适当的 ViewModel
来耦合视图及其逻辑。这使得你的软件设计更加灵活,因为 View
和 ViewModel
之间的唯一依赖关系是通过 Binding 建立的。
视图和代码逻辑的硬编码依赖(如 codebehind 方法中使用)会限制应用程序的动态性,因为视图和代码以直接的方式耦合。
对于完全不熟悉此概念的人,我建议您访问以下链接:
http://en.wikipedia.org/wiki/Model_View_ViewModel
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
为什么选择 MVVM?
一旦你将应用程序设计为 MVVM
模式,你就可以简单地替换一个视图,只需保持 Binding 约定,而不必修改逻辑。
反之亦然,你可以在不修改 View
的情况下切换 ViewModels
。
在使用 codebehind 方法时,这要困难得多(几乎不可能)。
在我们的示例中,我们使用 MVVM
模式,但此外,我们将逻辑从特定应用程序分离到 PCL 库。这将使我们能够在 Xamarin 的不同平台(如 Android、IOS 和 Windows Phone)上使用相同的库。
安装 mvvmcross nugget
在“管理 Nugget 包”窗口中搜索 mvvmcross,确保将其安装在 PCL 和应用程序项目上。
或者,直接输入
PM> Install-Package MvvmCross.HotTuna.Plugin.All -Version 3.2.2
在你的包管理器控制台中。
随着 nugget 完成安装,请注意,你的 PCL 和应用程序项目中会出现两个名为“ToDo-MvvmCross”的新目录,请逐步按照说明进行操作。
如果一切顺利,你可以编译并运行你的应用程序。你应该会得到类似这样的结果
探索 mvvmcross 项目结构
可移植类库 (PCL)
App.cs
这是你的 PCL 的主类,它继承自 MvxApplication,并且会在你的库创建时实例化一次。
Initialize() 方法
public override void Initialize()
{
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<ViewModels.FirstViewModel>();
}
此方法将遍历库项目中的所有类,并且所有以“Service”约定结尾的类都将作为单例使用 惰性实例化在你的 Mvx
对象中。
当然,你也可以手动完成
//Using Func
Mvx.RegisterType<TestService>(() => new TestService());
//using Interface as identifier
Mvx.RegisterSingleton<ITestservice>(new TestService());
你可以根据需要更改 Initialize 方法。
例如:
CreatableTypes()
.EndingWith("Handler")
.AsTypes()
.RegisterAsLazySingleton();
解释:现在它将遍历所有以“Handler”结尾的类,并使用惰性实例化,将它们注册为类型,而不是接口。
同时请注意,我们指定了应用程序将启动的 ViewModel。
RegisterAppStart<ViewModels.FirstViewModel>();
mvvmcross 中的依赖注入/IOC
依赖注入是一种 软件设计模式,其中一个或多个依赖项在解析对象类型时被注入或通过 引用 传递。
注册类型和接口
在 mvvmcross 中,Mvx
类有三种注册对象的方式:
RegisterType
– 根据你选择的重载函数,按接口或构造函数注册类型。
RegisterSingleTone
– 将对象注册为单例(整个应用程序生命周期只有一个实例)。
LazyConstructorAndRegistersingleTon
– 将对象注册为单例,并进行惰性构造函数实例化。这意味着,只有在调用 Mvx
类的 Resolve()
方法时,对象才会被实例化。
在 mvvmcross 中,有一个名为 Mvx 的类,它使用 IOC 来注册和解析依赖项。
解析类型和接口
你只能通过 Resolve()
方法解析已注册的对象,通过指定类型或接口。
建议先使用 CanResolve
方法或 TryResolve
,以确保不会抛出恼人的异常。
在通过 CreateTypes
方法或手动将类型注册到 Mvx
类后,你现在可以从应用程序中的任何位置访问这些类。
var filehandler = Mvx.Resolve<IFileHandlerAsync>();
有关更多信息,请参阅以下链接:
IOC - http://en.wikipedia.org/wiki/Inversion_of_control
DI - http://en.wikipedia.org/wiki/Dependency_injection
ViewModels 目录
mvvmcross nugget 自动添加的另一个组件是你库项目中的 ViewModels
目录。
所有 ViewModel 类(继承自 MvxViewModel)都存储在此处,并将通过名称约定链接到应用程序项目中的视图。
请注意,默认情况下,mvvmcross nugget 会在你的 ViewModels 目录中创建一个 FirstViewModel.cs 类,该类最终会链接到应用程序项目中 Views 目录中的 FirstView.cs。
名称约定是:
视图约定:[视图名称].cs
ViewModel 约定:[视图名称]Model.cs
MvxViewModel 和 MvxWindowsPage
在使用 mvvmcross 时,你将处理 Mvx
类,每个 ViewModel
类都继承自 MvxViewModel
,每个 View
都继承自 MvxWindowsPage
。
在遵循 MVVM
模式时,我们不会在 View 类中编写任何 codebehind,因此视图的全部逻辑将在相应的 ViewModel
中实现。
MvxViewModel 方法
public virtual void Start()
Init()
是在 ViewModel 中调用的第一个方法。
public void Init(IMvxBundle parameters)
Start()
在 Init()
方法之后调用,IMvxBundle
参数是一个对象,其中来自前一个 ViewModel
的 passed 数据作为 Key-Vaule
对传递,使用 Dictionary
作为数据结构。
所有传递的数据都存储为字符串,因此要与复杂对象一起使用,你需要执行序列化,这可能会严重影响性能。
通常,在处理复杂对象时,会使用另一个辅助类来完成这些任务。
public void Init(IMvxBundle parameters);
protected virtual void InitFromBundle(IMvxBundle parameters);
protected virtual void ReloadFromBundle(IMvxBundle state);
public void ReloadState(IMvxBundle state);
public void SaveState(IMvxBundle state);
protected virtual void SaveStateToBundle(IMvxBundle bundle);
这些方法用于从 bundle 存储和重新加载数据。通常在你应用程序进入后台,并且你希望保存一些可能丢失的数据时使用,因为 ViewModel 将被重新初始化。 当应用程序返回到前台时,保存的数据将被读取并如同 ViewModel 重新加载一样被处理。
调用顺序
在 ViewModel
创建时
- 构造函数 ()
- Init()
- InitFromBundle()
- Start()
在 ViewModel
销毁时
SaveStateToBundle()
应用程序项目
在我们的应用程序项目中,我们有一个名为 Views 的新目录、DebugTrsace.cs 类和 Setup.cs。
DebugTrace
继承自 IMvxTrace
接口,该接口实现了 3 个方法。
void Trace(MvxTraceLevel level, string tag, Func<string> message);
void Trace(MvxTraceLevel level, string tag, string message);
void Trace(MvxTraceLevel level, string tag, string message, params object[] args);
使用 System.Diagnostics.Debug
类进行日志记录。
安装
这是应用程序设置发生的地方。
这些是方法:
public Setup(Frame rootFrame) : base(rootFrame)
protected override IMvxApplication CreateApp()
protected override IMvxTrace CreateDebugTrace()
Setup
- Setup 类的构造函数。
CreateDebugTrace
– 在创建 DebugTrace
时调用,默认情况下 – 只返回 DebugTrace
类的实例。
CreateApp
– 在整个应用程序初始化并建立 mvvmcross 组件连接之前立即调用。在这里,你可以从应用程序项目注册到 IOC,并在 PCL 中使用 Mvx
类中的那些对象。
例如,如果你想从可移植库中的 ViewModel 调用 DialogMessage
对象,你无法通过直接调用该类来建立。因为你的项目没有相应的程序集引用。
在这种情况下,你可以创建实现某种功能的类,并在 CreateApp
方法完成之前,将其注册到共享的 Mvx
(IOC)对象。
protected override IMvxApplication CreateApp()
{
Mvx.RegisterSingleton<IMessageBox>(new MessageBoxHandler());
return new Core.App();
}
在 PCL 项目中声明接口,以便两个项目都能识别它。
在 ViewModel
中,简单调用 Mvx
类的 Resolve 方法来获取所需的 Mvx
对象实例。
Mvx.Resolve<IMessageBox>().ShowMessage(COMMENT_SUBMIT_SUCCESS);
现在,你的 ViewModel 中就有 DialogMessage
功能了。
视图
在你的 xaml 视图中,你可以看到基础 xaml 节点不再是 Page,而是 views:MvxWindowsPage,它是 mvvmcross 类型,codebehind 也继承自同一个类。
现在你可以创建你的视图并将控件绑定到 ViewModel(位于 PCL 中)。
摘要
Mvvmcross 是一个非常方便的跨平台应用程序开发平台,它使你的开发过程更加简单。
继续阅读有关 mvvmcross 插件和扩展的内容。还有很多值得探索的地方。