Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MvvmCross - Android: How to perform App initialization on Main Thread

I have an Android application using MvvmCross. The App launches via an MvxSplashScreenActivity as the main launcher and I provided a setup class deriving from MvxAndroidSetup.

It seems however that my MvxAndroidSetup.CreateApp() override is called on a ThreadPool thread (see https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Droid/Views/MvxBaseSplashScreenActivity.cs#L79).

What is the best way to ensure certain parts of my App Initialization are performed on the MainThread?

like image 488
Johannes Rudolph Avatar asked Dec 27 '22 04:12

Johannes Rudolph


1 Answers

Most of the modern platforms - WindowsStore, WindowsPhone and iOS - allow you to bundle a static Default.jpg (or similar) to entertain your users while your app starts.

Android doesn't do this - it simply launches your app using the Activity marked as the MainLauncher.

If your app needs to do some initialization work (as most MvvmCross apps do) then this leaves you with a choice - do you do that work on the UI thread (which then results in an unresponsive UI) or do you display a placeholder SplashScreen and then do the initialization work on the background thread.

This is what MvvmCross tries to allow you to do

  • it provides you with a splashscreen class
  • it overrides the OnCreate of the splashscreen to do the minimal work it can on the UI thread during the splashscreen OnCreate (during this time the UI is black which is horrible)
  • then it does the bulk of init on a threadpool thread - as @CheeseBaron has pointed out on MvxBaseSplashScreenActivity.cs#L79

The bulk of initialisation - loading types, starting services, recovering settings, loading language files, etc - shouldn't need to be done on the UI thread.

If there is some part of initialization that you need to do on the UI thread, then it's up to your app to work out how and when to marshal that work back to the UI - e.g.

  • by using MvxMainThreadDispatcher.cs
  • by deferring that task until a later time (e.g. using Lazy IoC which will be triggered by viewmodel creation)
  • by overriding the SplashScreen's OnInitialisationComplete method

However, obviously at no point should you try to marshal any long-lasting work onto the UI thread... the UI thread is for the UI, not for heavy calculation or for any blocking work.

You should aim to keep the UI responsive, even during startup.


Detailed note:

The above description covers the 'normal launch' of an app from e.g. the android Home page.

However, if you dive deeper, then this is not the only way an app can be started - it can also be started from push notifications, from recovering from being killed ("tombstoned" in WP speak) or from things like broadcast receivers.

In those situations, the MvvmCross app initialisation may occur in other ways than described above:

  • in the case of an MvxActivity being directly launched (e.g from push or after recovering from tombstoning), then the whole of Setup is currently run on the UI thread during the OnCreate of that activity - this isn't ideal and is something I would hope the framework can improve on in the future.
  • in the case of a background service starting, it's up to the app engineer to work out what to setup when - e.g. see Using MvvmCross from content providers and activities

One opportunity for an alternative startup route is to subclass the Android Application object - see http://developer.android.com/reference/android/app/Application.html

like image 124
Stuart Avatar answered Jan 19 '23 19:01

Stuart