问题
I've created a service in my application that listens for push notifications from GCM.
The service's OnMessage
method gets called correctly in all scenarios that I've tested: app running in foreground, app running in background and app not running. However, when the app is not running, the code is throwing a NullReferenceException
when I try to resolve dependencies with Mvx.Resolve
.
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
at Cirrious.CrossCore.Mvx.Resolve[IRepository] () [0x00000] in <filename unknown>:0
at MyApp.Android.Notifications.GcmService+<OnMessage>d__3.MoveNext () [0x00000] in <filename unknown>:0
Process my.app.droid (pid 7846) has died.
It appears that, since the app isn't running, the Setup
class has not been executed and the IoC container doesn't know how to resolve my types. Or, even worse, the Mvx
class has not been initialized and at all.
I can't seem to find documentation on the web on how to work around this.
Am I out of luck and have to try to launch my application with what information was sent in the notification and only perform the operations on my IRepository
once the app has fully launched?
Or is there a way to ensure that Mvx
is properly initialised when a service running while the app is closed is activated by the system? This, of course, would be the better option, since I'm likely to encounter this in other background services listening to internet access changes or location changes.
回答1:
Stuart Lodge's comment put me on the right track and helped my solve my problem, but I'll answer the question in detail myself for others who might have the same issue.
What I hadn't understood from the different documents online, is that an MvvmCross Android app is initialized through a MvxAndroidSetupSingleton
. This type has methods that, as far as I understand, can safely be called repeatedly to ensure that the singleton exists and is properly initialized:
var setupSingleton = MvxAndroidSetupSingleton.EnsureSingletonAvailable(context);
setupSingleton.EnsureInitialized();
All I had to do then, was call this code when a message is received on the notification service:
protected async override void OnMessage(Context context, Intent intent)
{
var setupSingleton = MvxAndroidSetupSingleton.EnsureSingletonAvailable(context);
setupSingleton.EnsureInitialized();
await MyMobileApp.EnsureDataStoreInitialized();
var logger = Mvx.Resolve<ILogger>();
logger.Send(LogLevel.Info, "Notification received");
}
If the app was running, it's basically a no-op, but if the app was closed, it will initialize MvvmCross running the Setup
class's methods, etc.
I then borrowed the concept and implemented an "Ensure"-type method on my app that will do part of the initialization that I normally do in my splash screen (mainly, ensuring that the data store exists).
Having initialized the MvxAndroidSetupSingleton
, I can then resolve dependencies as usual.
来源:https://stackoverflow.com/questions/24939573/how-is-mvvmcross-initialized-in-a-notification-service-when-app-is-closed-and-no