Xamarin.Forms: The App in 1.3

One of my goals for the New Year is to learn Xamarin.Forms well enough that I can begin doing some serious speaking on it.  To that end, I decided to rewrite my Score Predict personal project app using it; this would give me a sense as to maturity of the platform and its viability in future projects both personally and professionally.

My experience got off to a rocky start as I seemed to have caught Forms in the midst of upgrading to 1.3.  I had quite the struggle getting things to work.  With the help of Xamarin’s Jason Smith I was able to overcome my difficulties which really amounted to synching my NuGet package versions and updating the project file.

The biggest difference I have found so far in 1.3 is the way the App class is defined.  Before we saw things like this:

public class App
{
    public static Page GetMainPage()
    {
        return new ContentPage
        {
            Content = new Label
            {
                Text = "Hello, Forms !",
                VerticalOptions = LayoutOptions.CenterAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand,
            },
        };
    }
}

This would then be called by platform specific code to load in the page.  Here is an example:

    [Activity(Label = "Main Page", MainLauncher = true : AndroidActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Xamarin.Forms.Forms.Init(this, bundle);

            SetPage(App.GetMainPage());
        }
    }

You can see here, the reference to a static method which really seems incorrect given the features of C# and what .NET allows us to do.  Additionally, this sort of approach requires the developer understand the existing infrastructure of the target platform; which may not be desirable.  All in all, while this works but it could be done a lot better, I feel. The Xamarin guys thought so as well.

The new way utilizes a Forms specific base class for the platform specific launcher.  This base class provides a method LoadApplication which takes an instance of the custom App class and understands what that means for starting the application.  Here is an example of what your App class looks like in 1.3:

	public class App : Application
    {
		public App()
		{
			MainPage = new SplashPage ();
		}

		protected override void OnStart ()
		{
			base.OnStart ();
		}
    }

You can see the App class inherits from Application which is a new Forms specific class.  This class now allows you to override methods pertaining to the app’s lifecycle for the various platforms, including access to the Properties property which is a property bag that will take care of serialization of values for state persistence.

The main goal of the Application class, in addition to handling lifecycle events, the Application class also specifies to the MainPage which is what each platform will look at when loading the first page in the application, in this case the first page is SplashPage.

In order to load this appropriately, you need to call Forms.Init() and LoadApplication() in each platform like so:

iOS (AppDelegate)
    [Register("AppDelegate")]
    public partial class AppDelegate : FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            Forms.Init();
            LoadApplication (new App ());

			return base.FinishedLaunching (app, options);
        }
    }

One thing I will point out is, I noticed that it helps of you call the base FinishedLaunching method otherwise iOS seems to get confused.  This might be something Xamarin will fix in the near future.

Android (MainActivity)
    [Activity(Label = "ScorePredict", MainLauncher = true]
	public class MainActivity : FormsApplicationActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            Xamarin.Forms.Forms.Init(this, bundle);
			LoadApplication(new App());
        }
    }

Windows Phone (MainPage)

    public partial class MainPage : FormsApplicationPage
    {
        public MainPage()
        {
            InitializeComponent();

            Forms.Init();
            LoadApplication(new ScorePredict.App());
        }
    }

Overall, the change using a base class and for each platforms launching mechanism hides a lot of code and enables developers to really focus on what their application does, not how it starts.  I love the new approach and I see a lot of potential with this platform for the majority of apps for platforms.  Already, as I write this, I am working on a new version of my Score Predict app and, because I am taking this approach, I am basically doing all three platforms at the same time.

Once we are able to add in IoC and MVVM this is going to be the preferred way, for me, to develop applications in Xamarin, pending a custom UI that can be generalized of course.

Cheers.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s