Prism with WinRT how can I force a fresh start when resuming from termination? - windows-runtime

I am building a WinRT App, that uses proximity, and WiFi direct for peer to peer communication. As a result, when the app terminates, and then resumes I need it to start fresh (the connections will be closed, and can't be reopened without user interaction). The problem is that the Prism MvvmAppBase class that I am inheriting my app from is doing something that is causing it to try to resume from a saved state (that does not exist) and the app ends up on the last screen shown, but there is no ViewModel backing it, and so depending on the view, it will just sit unresponsive, or crash.
I am looking at this guide for guidance, and it says that unless there is a way to start fresh, but I cannot seem to find how to actually do that. http://msdn.microsoft.com/en-us/library/windows/apps/xx130647.aspx
I have been hacking around in the App.cs file to try and get it to work. There is really nothing at all in the App.cs file now except for the unity container and prism bootstrapping, and a call to NavigationService.Suspending() in the Suspending event handler.
The bootstrapping looks like this, but it is never called when the app is resumed from Termination.
protected override async void OnLaunchApplication(LaunchActivatedEventArgs args)
{
await BootStrapper.Config(_container);
await BootStrapper.RegisterPrismInstances(_container, NavigationService, SessionStateService, FlyoutService);
NavigationService.Navigate("Main", null);
}
If anyone has dealt with this before, and can point me in the right direction, I would really appreciate it.

When a Prism WinRT app is re-launched after being Terminated Prism will try to restore the application state, the Frame's navigation stack and the Frame's state before being terminated (which will navigate to the last opened page and try to restore any properties in the view model that are marked with the RestorableState attribute.)
By looking at the MvvmAppBase's source code it seems that there are a couple of things you could try to prevent Prism for saving / restoring the application state:
Create a default constructor in your App class that would clear the handlers of the Suspending event. The default constructor of the MvvmAppBase registers to this event and saves the state when it's raised.
Override the OnLaunched method of the base class. In it, after executing the base method, check if the previous executing state is Terminated. If so, you could clear the navigation history of the NavigationService and navigate to your start up page. The saving and restoring operations will still execute though, so any registered service will still be restored to its previous state. (This cannot be done in the OnLaunchApplication as it's not invoked if the application's state was successfully restored.)
Also, you could also try to completely remove this functionality from the MvvmAppBase class. However, most of its methods related to saving / restoring the application state are private, so you might as well drop the MvvAppBase, copy its entire code in your App class and edit it accordingly.
I have not tried any of the approaches listed above so I'm unaware if they could generate any problem, but they might help you as a starting point.

Related

ServiceLocationProvider is null when launched as a Share Target

I'm using MVVM Light and everything is fine except when launching my Windows Phone 8.1 WinRT app as a Share Target.
When I try to assign MainViewModel viewModel = ServiceLocator.Current.GetInstance<MainViewModel>(); I get an exception for ServiceLocator.Current.
Exception Message: ServiceLocationProvider must be set.
Do I need to do something extra in App.xaml.cs OnShareTargetActivated event to insure the Locator is running?
UPDATE:
A ShareTarget page needs to be thought of as a small extension of your app. It seems that not all of the app's resources are loaded (including app-wide resources in App.xaml). So I just created a new instance of MainViewModel in the share page's constructor, loaded only the things I need for the share to complete, save the information and call ShareOperation.ReportCompleted. This returns the user back to the app that is sharing.
I still haven't found a good solution for getting other resources in my ViewModel, but this works for now.
This indicates that the following line has not been executed:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
This line will instruct the ServiceLocator class to use the SimpleIoc.Default instance as its ServiceLocator.Current. When you run your app as a Share target, the initialization is slightly different and probably the ViewModelLocator doesn't get initialized. You need to find a good location to perform the initialization before you use the ServiceLocator.
Cheers
Laurent

How to save state to the server in an AS3 Flex App before unloading the SWF?

I would like to use URLLoader to save my user's state to the server when the SWF is shutting down. I have a function named saveUserState which saves the user's state correctly when called at any point except shutting down.
Within my creationComplete function, how do I add an event listener to know when the main SWF is unloading?
I have tried:
addEventListener(Event.REMOVED_FROM_STAGE, saveUserState, true, 1000, true);
But my saveUserState function is not being called when the SWF is closed. I've searched and found other answers on the Internet which require an external interface to JS which does the invocation on the browser's onbeforeunload, but I see issues with IE and I'd like to avoid requiring this JS. I also see this answer, but it's not marked as accepted and I found it not to work.
Is this possible?
Try to save user state to server when state changed. In this case you will be protected from unexpected events like disconnect or power or internet failure.

multiple instances of view and view model in memory

We have a windows phone 8 application in which we are using mvvm light having four , five views , and about same number of view models. One day we observed that the size of the application is increasing with usage and eventually reaches more than 100 mb and eventually crashes.After lot of testing what we are able to understand is that every time we navigate to a view , its instance is created and stored in the memory.It was observed that all the instances of the view and the view model are living in the memory and thus increasing the space on the ram. We also confirmed the same by defining finializer on view class and view model , on closing the application the finializer is called exactly the same number of times the page was navigated to. We are binding the datacontext of the view to respective view model in xaml. One of the main view has an ad control , so size increases very fast if user navigates to that view multiple times. How to resolve this issue. What I am unable to understand is the view should be destroyed once the user presses the back button, but this is not happening . Any help would be much appreciated.
We found a solution to this by adding below line of code to code behind.
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
Messenger.Default.Unregister(this);
if (e.NavigationMode == NavigationMode.Back)
{
DataContext = null;
}
}
What we are doing above is that we are unregisterring all the message handlers for the page and assigning the DataContext to null. In our case the datacontext was assigned in the xaml only and messenge handlers were registered in the OnNavigatedTo event of the page. But what is still unclear that on navigating back from the page , the page object should have died automatically . And should this line of code be added to all the mvvm light project pages and if so then why is it not common practice.
The reason you are leaking View memory is because you are in some way subscribing to events of the ViewModel from inside your Views. Either refactor those subscriptions to be WeakEvent subscriptions or remove them inside your OnNavigatedFrom
Use an IOC Container to maintain a single instance of all the ViewModels.
One of the options would be to use SimpleIoc that comes with MVVM Light.
Best tutorial to learn MVVMLight SimpleIoc

Flex WebService invokeAllPending never called

I been using the WebService and Operation classes of Flex Framework for a while, and after some ups and downs (more downs than ups, haha) I'm in process of refactoring all its uses with some utility classes/wrappers.
After browsing a little of the code of mx.rpc.soap.Operation I noticed that when you use the method "send" and the web service is not ready then the call is queued to an internal array (pendingInvocations:Array in line 1142). But the funny thing is that the invocations in the queue are never called again.
This is a bug or there is something I'm doing wrong?
I'm considering extending mx.rpc.soap.Operation, overriding "send" and testing if there are invocation queued, calling invokeAllPending (a mx_internal method that pops all the queued invocations) my self.
But the other problem is that that method is mx_internal, so I don't know if Adobe is gonna change it any time soon.
Any advice?
Thanks in advance
It's not a bug. Take a look at the definition for AbstractWebService; it defines a method called unEnqueueCalls (which is right up near the top of the list of awkward method names that I've seen :)). This method loops through all the operations in the webservice and invokes the pending calls for each operation by calling that invokeAllPending method you found.
unEnqueueCalls is itself called from the WebService class, in the wsdlFault and wsdlHandler methods, one of which runs when your WSDL is finished loading.
So, everything is all accounted for; you don't need to override anything.

How do I attach a global event listener?

I am working on an AIR application:
The main window is like a dashboard. With the menu bar, I can open other windows with dashboard details. When I close these, I'd like to refresh the main window.
I tried to use an event listener, but the result is not good. If I open detail windows directly from the main window, I know how to add an event listener - and it works - but I don't know how to do it, if the detail window is opening from the menubar!
Thanks for helping me.
A Singleton is what you are looking for. Just put an event dispatcher inside and you will be able to listen from everywhere in the application.
A Singleton is like having a unique instance of an object in memory, so anyone modifying a variable inside that object ( or sending events throught ) will be modified for everyone.
Here is an example of code on how to use it.
http://life.neophi.com/danielr/2006/10/singleton_pattern_in_as3.html
Note: Singletons are powerful and dangerous at the same time, there is a lot of talk about how to use them, please read a little more about that if you are considering building a big project.
Hope it helps!
The issue is that you're performing business logic from a View. Don't do this. Instead, dispatch an event from each menu rather than directly opening the window from within it. Listen for those events at a higher level, and then you can either directly listen to the new windows you have opened, or you can create a base window Class that exposes a variable of type IEventDispatcher. If you populate that variable with the same event dispatcher, what you wind up with is called an "event bus," and you can listen on that for events.
This architecture requires a little more thought than using a Singleton, but it avoids the tight coupling and other issues you'll run into by introducing one into your project.
You can listen to an object (EventDispatcher) directly by adding an event listener to it, or if the dispatcher object is on the displaylist, such as a Sprite, you could listen at the stage level with the capture parameter set to true.
But the main caveat is that the dispatcher must be on stage for you to catch this event.
Your main window listens to stage (with capture = true):
stage.addEventListener("MY_CUSTOM_EVENT", handle_custom_event, true);
private function handle_custom_event(e:Event):void
{
var sub_window:Object = e.target;
// do something to your sub_window
}
Your sub window can dispatch events like this:
dispatchEvent(new Event("MY_CUSTOM_EVENT"));
But (ab)using the stage as a message passing infrastructure for custom events in this way is a little messy. You could consider a more formal message passing architecture if you really want this kind of communication. Even a static MessageBus class would at least quickly help you identify where you use this in your codebase. Either way, you'll have to be careful about references and memory leaks.