Xamarin + PCL + MVVM — как облегчить написание мобильных приложений под разные платформы

в 13:59, , рубрики: .net, android, cross-platform, mobile development, mvvm, pcl, xamarin, метки: , , , , ,

Как-то совершенно незаслуженно обделена вниманием платформа Xamarin 2.0, и я б хотел начать описание всех его замечательных свойств

Прежде всего, что такое Xamarin?

Xamarin это коммерческий продукт, основанный на open-source проекте Mono, который позволяет использовать .Net framework, в том числе язык C#, для кроссплатформенных разработок.

Основные свойства:

  • C# для написания приложений под Android, iOs и Windows8. Поддержка LINQ и async/task
  • Native UI, Native Peformance — код компилируется под конкретную платформу и использует native UI контроли
  • Visual Studio и все его plugins, включая ReSharper, NUnit testing…
  • Xamarin Studio, которая похожа на Visual Studio, но доступна также и для Mac
  • Использование .Net библиотек
  • Использование других готовых native компонент, обвернутых в C#
  • Графический редактор для Андроида

image

MvvmCross

В этом примере я буду использовать модель MVVM, для тех кто с ней не знаком, то вкратце цитата из википедии:

Шаблон Model-View-ViewModel

Паттерн MVVM делится на три части:
Модель (Model), так же, как в классической MVC, Модель представляет собой фундаментальные данные, необходимые для работы приложения.
Вид/Представление (View) — это графический интерфейс, то есть окно, кнопки и.т.п. Вид является подписчиком на событие изменения значений свойств или команд, предоставляемых Моделью Вида. В случае, если в Модели Вида изменилось какое-либо свойство, то она оповещает всех подписчиков об этом, и Вид в свою очередь запрашивает обновленное значение свойства из Модели Вида. В случае, если пользователь воздействует на какой-либо элемент интерфейса, Вид вызывает соответствующую команду, предоставленную Моделью Вида.
Модель вида (ViewModel, что означает «Model of View»[1]) является с одной стороны абстракцией Вида, а с другой предоставляет обертку данных из Модели, которые подлежат связыванию. То есть она содержит Модель, которая преобразована к Виду, а также содержит в себе команды, которыми может пользоваться Вид, чтобы влиять на Модель.

Для кроссплатформенной имплементации этого шаблона, лучшей библиотекой (к тому же open source) является MvvmCross. Ее разработчик замечательно ее поддерживает и практически мгновенно откликается на любой вопрос.

Начнем

Для примера мы создадим простое приложение для подсчета чаевых. В зависимости от нашей щедрости и суммы счета она подсчитает размер чаевых, которые мы хотим оставить.

Установка

Прежде всего, нам необходимо зарегистрироваться и установить Xamarin Studio. Сам шаг довольно таки простой, никаких проблем я не заметил. Автоматически установятся Java, ADT, plugin для Visual Studio и библиотеки Mono.

Создание проекта

Почти любое приложение будет содержать несколько проектов.

  • Один из них будет 'core', который будет кроссплатформенный и содержать как можно больше кода: view models, общение с сервером, протоколы, обьекты даты и т.д.
  • UI проект для каждой платформы. Этот код не может быть общим, так как в нем используются компоненты, специфичные для платформы

Создаем New Project в Visual Studio, выбираем Visual C#, Windows, Portable Class Library.
Создаем проект TipCalc.Core и solution TipCalc. Выбираем опцию Windows Phone 7.5 and higher.
Хочу заметить, что пока поддерживается только версия .Net 4.0, но это должно измениться буквально в этом месяце.

Картинки

image

image

Удаляем Class1.cs, он никому не нужен
Добавляем библиотеку MvvmCross через NuGet. Для примера мы выберем Hot Tuna Start Pack, который включает в себя несколько начальных файлов.
Важно убедиться, что установлена последняя версия NuGet Package Manager, как минимум 2.5

Картинкa

image

После успешной установки мы увидим два новых файла: App.cs, в котором производится начальная инициализация MvvmCross, и файл FirstViewModel.cs в папке ViewModels. С точки зрения правильного программирования, я должен переименовать имя класса FirstViewModel на TipViewModel, но для упрощения примера так и оставим.

FirstViewModel класс наследует от MvxViewModel, это класс библиотеки MvvmCross и позволяет нам в дальнейшем посылать сообщения UI, когда данные изменились. Этот класс имплементирует INotifyPropertyChanged и его аналогия в WPF это BaseViewModel.
Добавим в этот класс 3 свойства: SubTotal (сумма счета), Generosity (щедрость) и Tip (чаевые, которые мы оставим). И перерасчет чаевых, в зависимости от них:

Код всего класса

using Cirrious.MvvmCross.ViewModels;

namespace TipCalc.Core.ViewModels
{
    public class FirstViewModel 
		: MvxViewModel
    {
        public FirstViewModel()
        {
        }

        public override void Start()
        {
            _subTotal = 100;
            _generosity = 10;
            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 = SubTotal * ((double)Generosity) / 100.0;
        }    
    }
}

Компилируем, ура, библиотека 'core' готова.

Клиент на Андроиде

Теперь мы хотим увидеть нашу логику на живом экране/телефоне/планшете. Так будет выглядеть его эскиз:
image

В том же solution добавим новый проект, но его тип будет Android -> Android Application. Назовем его TipCalc.UI.Droid
Если все нормально установлено, то мы увидим такую картинку:

Картинкa

image

Удаляем Activity1.cs и Main.axml из проекта.
Добавляем точно также, через NuGet, тот же пакет MvvmCross — Hot Tuna Starter Pack. Мы увидим в проекте новые файлы:

  • SplashScreen.cs — начальный Activity для аппликации
  • Setup.cs — иницализация MvvmCross и привязки ее к 'core'
  • FirstView.cs — Activity для нашего FirstViewModel
  • FirstView.axml — и его layout

Добавим в reference проект TipCalc.Core.csproj

Картинкa

image

Теперь мы нарисуем сами контроли.
Для этого откроем FirstView.axml и отредактируем его или в графическом редакторе или в xml редакторе. Мы добавим туда LinearLayout, TextView, EditText, SeekBar.
Через MvxBind мы свяжем свойства контроля с свойством нашего ViewModel.
Должна получиться вот такая картинка:

Картинкa

image

Если мы напишем такой код:

FirstView.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>

Важно заметить как мы делаем связывания свойств контролей. Свойство Text элемента TextView связывается (двусторонне) с свойством Tip нашего класса FirstViewModel посредством строчки local:MvxBind=«Text Tip» внутри самого описания контроля. Во всем остальном файл axml абсолютно идентичен любому layout в Андроиде.

Сохраняем, компилируем и запускаем. Вуаля, мы меняем сумму счета или нашу щедрость и чаевые автоматически меняются.
image

Итоги

  • Мы установили Xamarin Studio
  • Мы построили кроссплатформенную библиотеку с общей логикой
  • Мы создали приложение для Андроида, которая общается с логикой посредством MvvmCross (в этом нет необходимости, но Mvvm это круто)

Что мы упустили

  • Как работает Xamarin
  • Что такое Mvvm, как это имплементировано в MvvmCross и какие дополнительные возможности мы можем получить
  • Мы не построили примеры для iOs и Windows8
  • И много много другого
Источники

Xamarin
MvvmCross project
MvvmCross tutorial
MvvmCross tutorial video

Автор: Don_Eric

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js