How can I get ILifetimeAware to work?

Sep 1, 2012 at 9:02 AM
Edited Sep 1, 2012 at 9:04 AM

I try to implement lifetime Management within my app and therefore write the following line: 
public class MainPageViewModel : NotifyPropertyChangedBase, INavigationAware, ILifetimeAware
But non of the functions OnExiting, OnResuming, OnSuspending get called.
Is there anything else I Need to do?

Sep 1, 2012 at 4:14 PM

I'd recommend looking at the LifetimeManagerFixture.cs in the framework source code on how to use this.

I'm still new to this framework, but it looks like you need to create a ILifeTimeAware class and register it with the LifeTimeManager class.

 

Sep 1, 2012 at 6:22 PM

Finally I was able to solve it - I really should learn more about MEF.
The solution is the following:
[ImportingConstructor]
public MainPageViewModel(INavigationManager navigationManager, ILifetimeManager lifetimeManager)

and then lifetimeManager.Register(this)

Sep 1, 2012 at 6:41 PM

Ok, it only solves half of the issue.
OnSuspending gets called, but not OnExiting and OnResuming...

Sep 1, 2012 at 8:28 PM
Edited Sep 1, 2012 at 8:28 PM

I got the OnSuspending and OnResuming to work fine, but I'm not sure how to simulate the OnExiting.

Here is my LifetimeAwareService Class:

    public class LifetimeAwareService : ILifetimeAware
    {
        public LifetimeAwareService()
        {
        }

        public Task OnExiting()
        {
            return Task.FromResult<bool>(true);
        }

        public Task OnResuming()
        {
            return Task.FromResult<bool>(true);
        }

        public Task OnSuspending()
        {
            return Task.FromResult<bool>(true);
        }
    }

And here is my AppBootstrapper:

    public class AppBootstrapper : OkraBootstrapper
    {
        protected override void SetupServices()
        {
            base.SetupServices();

            LifetimeAwareService ltService = new LifetimeAwareService();

            LifetimeManager lifetimeMgr = new LifetimeManager();
            lifetimeMgr.Register(ltService);
        }
    }

 

 

Coordinator
Sep 2, 2012 at 11:43 AM

You seem to have the right idea regarding needing to register for the ILifetimeAware events in the view-model. The Okra lifetime events were mainly designed to be used from global services (such as the LifetimeAwareService of jjbravo) rather than directly from the view-models. There are cases however where being able to identify suspension/resuming in a view-model is useful and I'm looking into the best way to implement this. If you are able to disclose the scenario you are trying to implement that would be very useful.

As a workaround for the moment you can indeed import the ILifetimeManager into your view-model and register it manually. You may want to think about if you want lifetime events to be fired if the user has navigated to a different page of you application. If you still want them firing in the background then a separate service might be better. Alternatively if you want them constrained to the lifetime of the page being visible you can implement the INavigationAware interface (which is automatically registered for view-models so you don't need to do this manually) and register/unregister for the ILifetimeAware events in the NavigatedTo(...) and NavigatingFrom(...) methods. Note that if you have a navigation structure such as 'HomePage'>'ChildPage' don't make the ChildViewModel depend on the HomeViewModel (since after termination Okra may create the ChildPage and only create the HomePage lazily on back navigation).

Regarding some of the events not being fired correctly - I need to look into this and get back to you...

Andy

Coordinator
Sep 2, 2012 at 8:01 PM

Okay, I've checked out the events that get fired with the ILifetimeAware interface,

  • OnSuspending/OnResuming - I have tested these with both the LifetimeAwareService and by registering a view-model. @aschabus: How are you testing this? I recommend using the Visual Studio Suspend/Resume buttons.
  • OnExiting - You are correct. This never gets called - Okra is simply forwarding on the CoreApplication.Exiting event which never seems to be called (within the lifetime of anything that is listening to it). I will remove this from future versions of Okra as the recommendation seems to be to handle the suspending event rather that try to observe app closing.

@jjbravo: Be careful with creating a new LifetimeManager using the constructor. In general these are singletons and should be imported by MEF - when closing an application with Alt-F4 your code seems to miss the final OnSuspending call (NB: You have to wait for ~10sec after app closing for this to be observed). Instead you should use,

public class AppBootstrapper : OkraBootstrapper
{
    [Import]
    public ILifetimeManager LifetimeManager { get; set; }

    protected override void SetupServices()
    {
        LifetimeAwareService ltService = new LifetimeAwareService();
        LifetimeManager.Register(ltService);
    }
}
Coordinator
Sep 2, 2012 at 8:05 PM

One more note from MSDN - "Application lifecycle (Metro style apps)" regarding OnExiting - looks like this should not be used and I will remove from Okra,

"There's no special event to indicate that the user has closed an app. After an app has been closed by the user, it's suspended and terminated, entering the NotRunning state within about 10 seconds. If an app has registered an event handler for the Suspending | suspending event, it is called when the app is suspended. You can use this event handler to save relevant application and user data to persistent storage."

 

Sep 2, 2012 at 8:39 PM

Thanks a lot - please get me right; I like the base idea behind the Framework and therefore I try to find out, how it it was designed to be used - because I know that this is important for any Framework. And as for most Frameworks, it is not that easy to find this out by reading through the code.
One more question about this - how can I find out, when an application was restarted after terminated. So that I know when I should/can restore the state from the file?

Sep 2, 2012 at 9:19 PM

Sorry for the too fast reply - ok maybe it's too late for work here...
I found the solution at actually I think it's a very nice one.

Sep 3, 2012 at 4:49 AM
AndyWilkinson wrote:

@jjbravo: Be careful with creating a new LifetimeManager using the constructor. In general these are singletons and should be imported by MEF - when closing an application with Alt-F4 your code seems to miss the final OnSuspending call (NB: You have to wait for ~10sec after app closing for this to be observed). Instead you should use,

public class AppBootstrapper : OkraBootstrapper
{
    [Import]
    public ILifetimeManager LifetimeManager { get; set; }

    protected override void SetupServices()
    {
        LifetimeAwareService ltService = new LifetimeAwareService();
        LifetimeManager.Register(ltService);
    }
}


Thank Andy! I'm still new to all this. Still learning about MEF.