zoukankan      html  css  js  c++  java
  • Xamarin.Android之MvvmCross

    欢迎大家加入以下开源社区

    Xamarin-Cn:https://github.com/Xamarin-Cn

    Mvvmcross-Cn:https://github.com/Mvvmcross-Cn 

    (另外微信订阅号 Xamarin 所有者@善友兄也给予了运营权限,后面将开始陆续运营起来,给大家推送相关的文章)

    简介

    相信做了开发有一定经验的人都知道IOC的存在,而Xamarin.Android中还没有IOC的存在。特别是在Xamarin.Android下,如果仅仅只是显示简单的数据,就需要通过很多的FindViewById来查找组件,并且还要负责呈现,今天我们将通过学习MVVMCross组件来简化这些操作,达到PCL部分的最大化,下面我们以一个官方的DEMO来学习。

    题外话:

    由于公司的发展需要,需要招聘Xamarin方面的人才,如果你对Xamarin感兴趣的可以直接联系楼主,现在我们要召集8个人进行这方面的培训,所以只要有C#基础,并且有很强的兴趣都可以来。并且在产品完成后我们将会把开发的经验都撰写成博客发表,造福整个Xamarin(Q+976691141)。 

    PCL部分

    基础准备

    首先我们需要新建一个名为“TipCalc.Core”的“类库(可移植)”的项目,并且我们需要按照下图选择对应的平台:

    如果你的平台没有红色框住的部分也没有问题的,因为当前主流的PCL的方案是Profile259,如果你要查看你新建的类库是不是259可以查看项目的csproj文件,就是{项目名}.csproj,用记事本打开,然后定位到这个位置就可以看到了:

    警告:

    如果上面的PCL部分你按照我的选择之后,确定按钮是禁用的,就需要跟着下面的教程来解决这个问题,首先我们需要打开下面这个文件夹:

    C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETPortablev4.5ProfileProfile78SupportedFrameworks

    将该文件夹中的以下文件复制:

    如果不存在“Xamarin.iOS.Unified.xml”也没有关系,之后我们打开下面这个文件夹:

    C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETPortablev4.5ProfileProfile259SupportedFrameworks

    将上面的文件复制到其中,然后重启VS就可以解决问题了。

    项目搭建

    删除Class1.cs文件

    我们并不需要使用该文件

    安装MvvmCross

    我们打开“程序包管理器控制台”输入以下指令后回车:

    Install-Package MvvmCross.HotTuna.MvvmCrossLibraries

    添加Tip Calculation 服务

    创建一个名为“Services”的文件夹,并在该文件夹中新建一个名为“ICalculation”的接口,具体的内容代码如下所示:

    1 namespace TipCalc.Core.Services
    2 {
    3     public interface ICalculation
    4     {
    5         double TipAmount(double subTotal, int generosity);
    6     }
    7 }

    并在该文件夹中新建一个Calculation类实现上面的接口,具体代码如下:

     1 namespace TipCalc.Core.Services
     2 {
     3     public class Calculation : ICalculation
     4     {
     5         public double TipAmount(double subTotal, int generosity)
     6         {
     7             return subTotal * ((double)generosity)/100.0;
     8         }
     9     }
    10 }

    以上部分在实际项目中我们可以认为是应用服务层。

    添加视图模型

    视图模型将会连接最终的界面与上面的服务层,而为了达到这些效果,我们的视图模型必须继承自MvxViewModel。下面我们先新建一个ViewModels文件夹并新建一个TipViewModel类,具体的代码如下所示:

     1 namespace TipCalc.Core.ViewModels
     2 {
     3     public class TipViewModel : MvxViewModel
     4     {
     5         private readonly ICalculation _calculation;
     6         public TipViewModel(ICalculation calculation)
     7         {
     8             _calculation = calculation;
     9         }
    10 
    11         public override void Start()
    12         {
    13             _subTotal = 100;
    14             _generosity = 10;
    15             Recalcuate();
    16             base.Start();
    17         }
    18 
    19         private double _subTotal;
    20 
    21         public double SubTotal
    22         {
    23             get { return _subTotal; }
    24             set { _subTotal = value; RaisePropertyChanged(() => SubTotal); Recalcuate(); }
    25         }
    26 
    27         private int _generosity;
    28 
    29         public int Generosity
    30         {
    31             get { return _generosity; }
    32             set { _generosity = value; RaisePropertyChanged(() => Generosity); Recalcuate(); }
    33         }
    34 
    35         private double _tip;
    36 
    37         public double Tip
    38         {
    39             get { return _tip; }
    40             set { _tip = value; RaisePropertyChanged(() => Tip);}
    41         }
    42 
    43         private void Recalcuate()
    44         {
    45             Tip = _calculation.TipAmount(SubTotal, Generosity);
    46         }
    47     }
    48 }

    通过上面的代码我们可以看到,视图模型的构造函数要求传入一个实现了ICalculation接口的参数,而这个过程将会有IOC帮我们完成。剩下的我们可以看到我们重写了Start方法用来给视图模型中的值赋初始值,并且在每个值改变的同时还调用了Recalcuate方法来重新计算。

    OK,完成这些之后,我们还需要一个启动项对依赖注入进行配置,并且指定初始显示的视图模型,我们直接在项目根目录下新建一个App类,并且该类需要继承自MvxApplication类,并在构造函数中写入以下代码:

     1 namespace TipCalc.Core
     2 {
     3     public class App : MvxApplication
     4     {
     5         public App()
     6         {
     7             Mvx.RegisterType<ICalculation,Calculation>();
     8             Mvx.RegisterSingleton<IMvxAppStart>(new MvxAppStart<TipViewModel>());
     9         }
    10     }
    11 }

    其中我们可以看到我们通过Mvx.RegisterType对IOC进行了配置,这样IOC才能够知道在需要ICalculation接口的时候实例化哪个类,而下一行的代码则是指定初始的视图模型,也就是首页,完成上面这些配置后我们的PCL部分完成了,可以通用于Android和IOS。

     

    Android UI呈现

    首先我们创建一个“Blank App(Android)”项目,项目名为“TipCalc.UI.Droid”。并将项目默认生成的MainActivity.cs文件和Resources/Layout文件夹下的Main.axml删除并添加TipCalc.Core.csproj引用。

    安装MvvmCross

    跟PCL部分一样,我们还需要安装对应的类库:

    Install-Package MvvmCross.HotTuna.MvvmCrossLibraries

    添加MvvmCross Android绑定资源

    该部分是为了我们能够在界面中使用bind属性,所以我们需要在Resources/Values文件夹下新建一个xml资源,名字可以为“MvxBind”,对应的内容如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <resources>
     3   <declare-styleable name="MvxBinding">
     4     <attr name="MvxBind" format="string"/>
     5     <attr name="MvxLang" format="string"/>
     6   </declare-styleable>
     7   <declare-styleable name="MvxListView">
     8     <attr name="MvxItemTemplate" format="string"/>
     9     <attr name="MvxDropDownItemTemplate" format="string"/>
    10   </declare-styleable>
    11   <item type="id" name="MvxBindingTagUnique"/>
    12   <declare-styleable name="MvxImageView">
    13     <attr name="MvxSource" format="string"/>
    14   </declare-styleable>
    15 </resources>

    添加启动类

    虽然PCL中有启动项了,但是我们需要在特定中进行注册,所以我们还需要新建一个Setup类,并且该类的主要内容如下:

     1 namespace TipCalc.UI.Droid
     2 {
     3     public class Setup : MvxAndroidSetup
     4     {
     5         public Setup(Context applicationContext)
     6             : base(applicationContext)
     7         {
     8         }
     9 
    10         protected override IMvxApplication CreateApp()
    11         {
    12             return new App();
    13         }
    14     }
    15 }

    主要作用就是将App实例化并返回,以便在特定平台中进行初始化。

    添加视图

    我们需要在Resources/Layout文件夹下新建一个视图名为View_Tip.axml,并且其中的内容如下所示:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     xmlns:local="http://schemas.android.com/apk/res/TipCalc.UI.Droid"
     4     android:orientation="vertical"
     5     android:layout_width="fill_parent"
     6     android:layout_height="fill_parent">
     7     <TextView
     8         android:layout_width="fill_parent"
     9         android:layout_height="wrap_content"
    10         android:text="SubTotal" />
    11     <EditText
    12         android:layout_width="fill_parent"
    13         android:layout_height="wrap_content"
    14         local:MvxBind="Text SubTotal" />
    15     <TextView
    16         android:layout_width="fill_parent"
    17         android:layout_height="wrap_content"
    18         android:text="Generosity" />
    19     <SeekBar
    20         android:layout_width="fill_parent"
    21         android:layout_height="wrap_content"
    22         android:max="40"
    23         local:MvxBind="Progress Generosity" />
    24     <View
    25         android:layout_width="fill_parent"
    26         android:layout_height="1dp"
    27         android:background="#ffff00" />
    28     <TextView
    29         android:layout_width="fill_parent"
    30         android:layout_height="wrap_content"
    31         android:text="Tip to leave" />
    32     <TextView
    33         android:layout_width="fill_parent"
    34         android:layout_height="wrap_content"
    35         local:MvxBind="Text Tip" />
    36 </LinearLayout>

    通过其中的内容我们可以看到,其中多了一个MvxBind属性,通过这个属性我们可以直接将控件的属性直接与ViewModel中对应的属性直接关联起来,这样我们可以省去与控件交互的部分,但是我们还是需要Activity来将界面与我们的ViewModel进行关联。

    添加视图类

    我们直接新建一个名为TipCalcView的活动,然后将其继承的类改成MvxActivity,具体的代码如下:

     1 namespace TipCalc.UI.Droid.Views
     2 {
     3     [Activity(Label = "Tip", MainLauncher = true)]
     4     public class TipView : MvxActivity
     5     {
     6         public new TipViewModel ViewModel
     7         {
     8             get { return (TipViewModel) base.ViewModel; }
     9             set { base.ViewModel = value; }
    10         }
    11 
    12         protected override void OnViewModelSet()
    13         {
    14             base.OnViewModelSet();
    15             SetContentView(Resource.Layout.View_Tip);
    16         }
    17     }
    18 }

    完成这些之后,直接运行,我们可以看到调整进度条的同时,Tip to leave的值会跟着动,完全是实时的。

     

    当然原生的方式与MvvmCross的方式是可以直接并存的。

  • 相关阅读:
    EMQ 解决方案之云平台物联网消息队列解决方案
    EMQ X Broker 3.1 Beta.2 发布
    MQTT 与 Kafka
    EMQ X 助力运营商搭建大规模 NBIoT 平台
    MQTT5.0 消息发布流程
    MQTT 5.0 新特性 |(一) 属性与载荷
    MQTT 5.0 正式成为OASIS标准
    Nginx + Docker 手动集群方式运行 EMQ
    WJQ与机房
    P1505 [国家集训队]旅游
  • 原文地址:https://www.cnblogs.com/yaozhenfa/p/4709952.html
Copyright © 2011-2022 走看看