歡迎你們加入如下開源社區android
Xamarin-Cn:https://github.com/Xamarin-Cngit
Mvvmcross-Cn:https://github.com/Mvvmcross-Cn github
(另外微信訂閱號 Xamarin 全部者@善友兄也給予了運營權限,後面將開始陸續運營起來,給你們推送相關的文章)微信
相信作了開發有必定經驗的人都知道IOC的存在,而Xamarin.Android中尚未IOC的存在。特別是在Xamarin.Android下,若是僅僅只是顯示簡單的數據,就須要經過不少的FindViewById來查找組件,而且還要負責呈現,今天咱們將經過學習MVVMCross組件來簡化這些操做,達到PCL部分的最大化,下面咱們以一個官方的DEMO來學習。app
題外話:ide
因爲公司的發展須要,須要招聘Xamarin方面的人才,若是你對Xamarin感興趣的能夠直接聯繫樓主,如今咱們要召集8我的進行這方面的培訓,因此只要有C#基礎,而且有很強的興趣均可以來。而且在產品完成後咱們將會把開發的經驗都撰寫成博客發表,造福整個Xamarin(Q+976691141)。 函數
首先咱們須要新建一個名爲「TipCalc.Core」的「類庫(可移植)」的項目,而且咱們須要按照下圖選擇對應的平臺:學習
若是你的平臺沒有紅色框住的部分也沒有問題的,由於當前主流的PCL的方案是Profile259,若是你要查看你新建的類庫是否是259能夠查看項目的csproj文件,就是{項目名}.csproj,用記事本打開,而後定位到這個位置就能夠看到了:spa
警告:code
若是上面的PCL部分你按照個人選擇以後,肯定按鈕是禁用的,就須要跟着下面的教程來解決這個問題,首先咱們須要打開下面這個文件夾:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile78\SupportedFrameworks
將該文件夾中的如下文件複製:
若是不存在「Xamarin.iOS.Unified.xml」也沒有關係,以後咱們打開下面這個文件夾:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259\SupportedFrameworks
將上面的文件複製到其中,而後重啓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。
首先咱們建立一個「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的方式是能夠直接並存的。