Now-a-days, making cross-platform apps have become a global phenomena. Usually the path taken by most of the developers among us are made of HTML5/JavaScript and awesome HTML5/JavaScript is now at the point that some of us wonder if we have done everything with the language we know. Well, this article is for all the C# fanatics out there who hae a good time behind them on C# and want to give Android a shot without changing their language. Xamarin to the rescue. You'll get more on Xamarin from
here.
Xamarin and MvvmCross
As per Xamarin goes it has a couple of options to build cross-platform applications. That includes xamarin.ios, xamarin.android and xamarin.forms. Usually if you want a cross-platform app with a single UI code behind then xamarin.forms might be what you want. But today I'm going to use xamarin.android with a PCL behind. I usually tend to keep my UI apart for various platforms and thus this route feels really nice. And since I'm from Windows Phone, I love MVVM, I love how the code is separated from the views and I'd love something like that over xamarin.android so I can share my viewmodels over xamarin.ios and xamarin.android. MvvmCross to the rescue!
MvvmCross is a cross-platform MVVM library that allows you to put a common PCL directly from xamarin.android and xamrin.ios. And you get most of the Mvvm data binding to view sugars around this too. So, what are we waiting for? Let's check MvvmCross out! And, MvvmCross resides
here.
Tools I've used here is mostly Xamarin Studio. You'd need a business subscription to build apps in Visual Studio.
Installing Xamarin
Installing Xamarin is pretty straight forward. Anyone can download the installer from
here and install it. If you have Visual Studio 2015 then probably you already have Xamarin templates installed. In any case it still works just fine with Visual Studio 2013.
Creating a PCL
Let's fire up our Xamarin studio and create a portable class library named NewsReader.cs. After you are done creating the project, delete the MyClass.cs file that has been created and right-click on the project name to go over the options. Move to the General section under build and you'll see the PCL profile you are using. I'm currently using the PCL profile 72 that targets .Net 4.5, Windows 8, Xamarin.Android and Xamarin.iOS.
Now, let's move on and install mvvmcross. To do that, all we need to do is right-click on the project name, Add -> Add nuget packages and you can select over all the Nuget packages available for use. We will install the MvvmCross - Hot Tuna Started Pack. Make it sure that you are downloading the latest stable version. Im using 3.5.0 here.
The moment you install the package, you will see some extra folders popping up and a C# class named App.cs popping up. Safely delete the ToDo-MvvmCross folder. You can definitely read what's inside, pretty gist of the entire tutorial here, but for our app purposes, that will not help.
Now, let's start peeking. Like every other mvvm library around MvvmCross has bestowed us with a ViewModels folder. If you go ahead and peek at it, you will see a class named FirstViewModel has already being populated and it's inherited from MvxViewModel. That's the base class for viewmodels in MvvmCross. Pretty neat, huh?
Now, for today, we are just going to fetch some news from a RSS feed and show the titles over a list. Let's move on and create a folder named Services. After creating that folder let's create an interface named INewsLoadingService. And quite frankly it is dead simple.
- namespace NewsReader.Services
- {
- public interface INewsLoadingService
- {
- Task<List<string>> LoadNews();
- }
- }
Now, we need to implement this very very very basic interface. Let's create a class under the Services folder and implement the INewsLoadingService.
- namespace NewsReader.Services
- {
- public class NewsLoadingService:INewsLoadingService
- {
- public NewsLoadingService ()
- {
- }
-
- #region INewsLoadingService implementation
-
- public async System.Threading.Tasks.Task<System.Collections.Generic.List<string>> LoadNews ()
- {
- HttpClient client = new HttpClient ();
- var data = await client.GetStringAsync ("http://www.bbc.co.uk/sport/football/premier-league/rss.xml");
- var News = ParseResponse (data);
- return News;
- }
-
- #endregion
-
- private List<string> ParseResponse(string text)
- {
- var xml = XDocument.Parse(text);
- var items = xml.Descendants("item");
-
- var list = items.Select(x => x.Element("description").Value.ToString()).ToList();
-
- return list;
-
- }
- }
- }
Now you can definitely see here that all I'm doing is fetching a set of news from a RSS feed and only getting their titles in a list of strings. Now, since our services are hooked up, let's move over to our FirstViewModel.cs and use this service. Our very simple ViewModel looks as in the following:
- namespace NewsReader.ViewModels
- {
- public class FirstViewModel
- : MvxViewModel
- {
- private string _title = "NewsReader";
- public string Title
- {
- get { return _title; }
- set { _title = value; RaisePropertyChanged(() => Title); }
- }
-
- private ObservableCollection<string> _newsCollection;
- public ObservableCollection<string> NewsCollection {
- get { return _newsCollection; }
- set { _newsCollection = value; RaisePropertyChanged (()=>NewsCollection);}
- }
-
- public FirstViewModel ()
- {
- LoadData ();
-
- }
-
- public async void LoadData()
- {
- INewsLoadingService service = new NewsLoadingService ();
- NewsCollection=new ObservableCollection<string>(await service.LoadNews ());
-
- }
- }
- }
Looks like we are all set with our very very very simple PCL. Now, let's add a new project to the solution. And it's going to be an Android project. Let's name it NewsReader.Android.
Now, we do have our Android project that would be based on our PCL. Now go to the project references and add our NewsReader PCL to the project reference.
Now, it's time to install MvvmCross in our Android project too. Kindly go to Nuget packages again and Install the MvvmCross - Hot Tuna Starter Pack into the Android project. We will definitely see some new stuff being populated there and we will see a Views folder with a FirstView.cs there. There is a new XML file in the Resources/values folder too named MvxBindingAttributes.xml. This file helps MvvmCross to allow data binding in the layouts. Now, let's delete MainActivity.cs and Resources/layout/MainView.axml since we don't need these anymore.
Now, as MVVM suggests, we need to hook up our viewmodel to our view and add the bindings. Before doing that let's go over our App.cs in the NewsReader project and have a peek.
- namespace NewsReader
- {
- public class App : Cirrious.MvvmCross.ViewModels.MvxApplication
- {
- public override void Initialize()
- {
- CreatableTypes()
- .EndingWith("Service")
- .AsInterfaces()
- .RegisterAsLazySingleton();
-
- RegisterAppStart<ViewModels.FirstViewModel>();
- }
- }
- }
This definitely feels familiar. You can see the app starts with FirstViewModel so I really don't need to explicitly hook up the viewmodel for FirstView since FirstViewModel starts the app. Now, let's go over NewsReader.Android and in the Views folder, let's check out FirstView.cs.
- namespace NewsReader.Android.Views
- {
- [Activity(Label = "View for FirstViewModel")]
- public class FirstView : MvxActivity
- {
- protected override void OnCreate(Bundle bundle)
- {
- base.OnCreate(bundle);
- SetContentView(Resource.Layout.FirstView);
- }
- }
- }
Now, you can definitely see the Activity annotation there and it also takes the activity label too. OnCreate is overridden with the FirstView.axml as the ContentView. So let's go over Resources/layout/FirstView.axml and see how to bind our FirstViewModel there.
- <?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-auto"
- 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:textSize="40dp"
- local:MvxBind="Text Title" />
-
- <MvxListView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:textSize="40dp"
- local:MvxBind="ItemsSource NewsCollection"
- />
- </LinearLayout>
Now, if you remember we had two properties exposed from our ViewModel. One were Title and the other were NewsCollection. For the title we used TextView, for all the XAMLites out there, TextView is just like TextBlock in Windows Phone. And if you look closely we bound local:MvxBind to the property we wanted to bind from our ViewModel. Now you might ask how MvxBind works here, it looks definitely a bit different from the ones we had in XAML. Now if you look closely, the first binding statement is "Text Title". That means we are binding the android:text property of the TextView with the Title property that has been exposed from our ViewModel.
Now, let's come to the next part that starts with the component MvxListView, it's basically a MvvmCross implementation of Android's ListView and it allows you to bind your collection in the viewmodel in here. So, if you look down the binding on local:MvxBind you'll find we're binding ItemSource as NewsCollection exposed from our viewmodel.
And that's it! Although it doesn't look so good, it's a start and seeing MVVM on Android is purely precious.
Pretty easy, huh? You can try the source code from Github
here. And the zipped one is attached too.