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 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”的接口,具体的内容代码如下所示:
namespace TipCalc.Core.Services
{
public interface ICalculation
{
double TipAmount(double subTotal, int generosity);
}
}
并在该文件夹中新建一个Calculation类实现上面的接口,具体代码如下:
namespace TipCalc.Core.Services
{
public class Calculation : ICalculation
{
public double TipAmount(double subTotal, int generosity)
{
return subTotal * ((double)generosity)/100.0;
}
}
}
以上部分在实际项目中我们可以认为是应用服务层。
添加视图模型
视图模型将会连接最终的界面与上面的服务层,而为了达到这些效果,我们的视图模型必须继承自MvxViewModel。下面我们先新建一个ViewModels文件夹并新建一个TipViewModel类,具体的代码如下所示:
namespace TipCalc.Core.ViewModels
{
public class TipViewModel : MvxViewModel
{
private readonly ICalculation _calculation;
public TipViewModel(ICalculation calculation)
{
_calculation = calculation;
} public override void Start()
{
_subTotal = ;
_generosity = ;
Recalcuate();
base.Start();
} private double _subTotal; public double SubTotal
{
get { return _subTotal; }
set { _subTotal = value; RaisePropertyChanged(() => SubTotal); Recalcuate(); }
} private int _generosity; public int Generosity
{
get { return _generosity; }
set { _generosity = value; RaisePropertyChanged(() => Generosity); Recalcuate(); }
} private double _tip; public double Tip
{
get { return _tip; }
set { _tip = value; RaisePropertyChanged(() => Tip);}
} private void Recalcuate()
{
Tip = _calculation.TipAmount(SubTotal, Generosity);
}
}
}
通过上面的代码我们可以看到,视图模型的构造函数要求传入一个实现了ICalculation接口的参数,而这个过程将会有IOC帮我们完成。剩下的我们可以看到我们重写了Start方法用来给视图模型中的值赋初始值,并且在每个值改变的同时还调用了Recalcuate方法来重新计算。
OK,完成这些之后,我们还需要一个启动项对依赖注入进行配置,并且指定初始显示的视图模型,我们直接在项目根目录下新建一个App类,并且该类需要继承自MvxApplication类,并在构造函数中写入以下代码:
namespace TipCalc.Core
{
public class App : MvxApplication
{
public App()
{
Mvx.RegisterType<ICalculation,Calculation>();
Mvx.RegisterSingleton<IMvxAppStart>(new MvxAppStart<TipViewModel>());
}
}
}
其中我们可以看到我们通过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”,对应的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MvxBinding">
<attr name="MvxBind" format="string"/>
<attr name="MvxLang" format="string"/>
</declare-styleable>
<declare-styleable name="MvxListView">
<attr name="MvxItemTemplate" format="string"/>
<attr name="MvxDropDownItemTemplate" format="string"/>
</declare-styleable>
<item type="id" name="MvxBindingTagUnique"/>
<declare-styleable name="MvxImageView">
<attr name="MvxSource" format="string"/>
</declare-styleable>
</resources>
添加启动类
虽然PCL中有启动项了,但是我们需要在特定中进行注册,所以我们还需要新建一个Setup类,并且该类的主要内容如下:
namespace TipCalc.UI.Droid
{
public class Setup : MvxAndroidSetup
{
public Setup(Context applicationContext)
: base(applicationContext)
{
} protected override IMvxApplication CreateApp()
{
return new App();
}
}
}
主要作用就是将App实例化并返回,以便在特定平台中进行初始化。
添加视图
我们需要在Resources/Layout文件夹下新建一个视图名为View_Tip.axml,并且其中的内容如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/TipCalc.UI.Droid"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="SubTotal" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="Text SubTotal" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Generosity" />
<SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="40"
local:MvxBind="Progress Generosity" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#ffff00" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Tip to leave" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="Text Tip" />
</LinearLayout>
通过其中的内容我们可以看到,其中多了一个MvxBind属性,通过这个属性我们可以直接将控件的属性直接与ViewModel中对应的属性直接关联起来,这样我们可以省去与控件交互的部分,但是我们还是需要Activity来将界面与我们的ViewModel进行关联。
添加视图类
我们直接新建一个名为TipCalcView的活动,然后将其继承的类改成MvxActivity,具体的代码如下:
namespace TipCalc.UI.Droid.Views
{
[Activity(Label = "Tip", MainLauncher = true)]
public class TipView : MvxActivity
{
public new TipViewModel ViewModel
{
get { return (TipViewModel) base.ViewModel; }
set { base.ViewModel = value; }
} protected override void OnViewModelSet()
{
base.OnViewModelSet();
SetContentView(Resource.Layout.View_Tip);
}
}
}
完成这些之后,直接运行,我们可以看到调整进度条的同时,Tip to leave的值会跟着动,完全是实时的。
当然原生的方式与MvvmCross的方式是可以直接并存的。
Xamarin.Android之MvvmCross的更多相关文章
- Xamarin. Android实现下拉刷新功能
PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...
- Xamarin.Android和UWP之MVVM的简单使用(二)
0x01 前言 前面一篇,Xamarin.Android和UWP之MVVM的简单使用(一),主要讲了MvvmLight的简单使用 这篇主要讲讲MvvmCross的简单使用,例子的话,还是和上篇的一样. ...
- Xamarin.Android和UWP之MVVM的简单使用(一)
0x01 前言 就目前而言,MVVM可以说是挺流行的,无论是web端还是移动端,web端的主要代表angularjs,avalonjs等, 移动端(xamarin,uwp)的代表应该是mvvmligh ...
- Xamarin.Android中使用ResideMenu实现侧滑菜单
上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin. Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜 ...
- XAMARIN.ANDROID SIGNALR 实时消息接收发送示例
SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...
- XAMARIN ANDROID 二维码扫描示例
现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile 做一个简单的 Android 条码扫描示 ...
- 我正在使用Xamarin的跨平台框架—Xamarin.Android回忆录
一.缘起 在自己给别家公司做兼职外包的时候,已经明确知道外包的活不是那么好干的,一般在经历了初期热血澎湃的激情后,逐渐冷淡,愤怒,再冷淡,再愤怒…,听上去好像高潮迭起,但令人尴尬的是,这高潮迭起我们都 ...
- APP并非一个人在战斗,还有API—Xamarin.Android回忆录
前言 一般来说,一个客户端APP并非独立存在的,很多时候需要与服务器交互.大体可分为两方面的数据,常规字符串数据和文件数据,因为这两种数据很可能传输方式不一样,比如字符串之类的数据,使用HTTP协议, ...
- Xamarin.Android通知详解
一.发送通知的机制 在日常的app应用中经常需要使用通知,因为服务.广播后台活动如果有事件需要通知用户,则需要通过通知栏显示,而在Xamarin.Android下的通知需要获取Notification ...
随机推荐
- go的mgo,连接未释放问题,连接泄露。
api启动几天后,卡住(连接失败,超时) 异常原因 mongo连接被占满,无法建立mgo连接,返回信息 查询点用端口可知,97%的连接被api项目占用. api项目的mongodb连接“泄露”,某处的 ...
- EF MYSQL 不能选择实体框架版本
web.config文件里面加如下配置,然后编译 <provider invariantName="MySql.Data.MySqlClient" type="My ...
- Tp field 字段是可以添加函数的
$info = M('Order')->alias('a') ->field('count(DISTINCT(a.order_user_id)) as buy_user_num,count ...
- Runloop 深入理解(转)
RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理.之后会介绍一下在 iOS 中,苹果是如何利 ...
- c++ chap1 to chap 3
#ifndef MAIN_H_INCLUDED#define MAIN_H_INCLUDED struct Course{ int id; std::string name;}; const int ...
- <转>浅析长度为0的数组
前面在看Xen的源码时,遇到了一段代码,如下所示: 注意上面最后一行的代码,这里定义了一个长度为的数组,这种用法可以吗?为什么可以使用长度为0 的数组?长度为的数组到底怎么使用?……这篇文章主要针对该 ...
- HTTP中的POST、GET区别
Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP ...
- JavaScript (jquery) 数组去重的算法探讨
方法很巧妙 但是要事先知道对应的name或其他属性名称 主键值只适用于已知数据对象进行调用: var arr1 = [{ name: ' ...
- 远程登录linux不用输入密码的方法
原创文章,欢迎阅读,未经博主允许禁止转载. ssh免密登录,使用密钥认证.执行以下命令,一路回车,就生成了密钥认证.然后,ssh登录,scp等都不用密码了. $ ssh-keygen -t rsa $ ...
- Spring 学习笔记 8. 尚硅谷_佟刚_Spring_使用外部属性文件
1,配置数据源 (1)添加驱动 (2)编写spring配置文件 <bean id="dataSource" class="org.springframework.j ...