What is a reliable (and immediately) way to detect if a user has closed the app with ALT-F4 or the close-gesture?
问题:
回答1:
According to the Application Lifecycle documentation there is no way to detect this event (See the section under "App close"). This type of state can be managed best using the ApplicationData class.
回答2:
Not really an exact answer to my specific question, but a way which solved my concrete problem for which I posted my question. Maybe it helps someone else:
Register to Window.CoreWindow.VisibilityChanged
:
Window.Current.CoreWindow.VisibilityChanged += CoreWindow_VisibilityChanged;
If the visibility has changed to false, this may be due to the closing of the app. Take care, the event will also fire for many other reasons, such as window changes via ALT-Tab:
void CoreWindow_VisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs args) {
if(!args.Visible){
// Action here
}
}
Please note: I suspect that MS has explicitely not provided an event which I was looking for, because heavy operations exactly at the moment the user closes the app will result in a less fluid user experience. However I think there are eligible cases where such an event makes sense and therefore people will use workarounds such as the one I provide here. If you use this or another workaround, take care to not create heavy load to the system.
回答3:
There are no doubt scenarios where you don't want to save state all the time in case the app is suspended. Wouldn't this be called "polling" (which is kinda bad and wasteful in other ways)? In my scenario, I have a timer that tracks time remaining, which is part of the state of the app, but I don't want to store this on every tick.
So, to do this properly, you'll need to:
- Track VisibilityChanged (as the original poster stated)
- Track Unloaded (whenever you navigate Back from the page, etc)
- Track when the page has been unloaded so you don't save stale cached pages that might be hanging around
To elaborate more on #3 above - I found that if I navigated forward from A -> B, then back to A, then to B again, I would end up with another cached page B hanging around. Then when the user left the app, I would get multiple VisibilityChanged events fired, some of these including old cached pages that I thought would have been destroyed but were not.
Here's the code that worked for me:
public void MyPage() // Constructor
{
Loaded += (sender, e) =>
{
if(!m_isLoaded)
{
m_isLoaded = true;
Window.Current.CoreWindow.VisibilityChanged +=
OnVisibilityChanged;
}
};
Unloaded += async (sender, e) =>
{
if (m_isLoaded)
{
m_isLoaded = false;
Window.Current.CoreWindow.VisibilityChanged -=
OnVisibilityChanged;
await SaveStuff();
}
};
}
protected void OnVisibilityChanged(object sender,
Windows.UI.Core.VisibilityChangedEventArgs e)
{
if (!e.Visible && m_isLoaded)
{
var dontAwait = SaveStuff();
}
}
// Called whenever the page is unloaded and state needs to be saved.
protected async Task SaveStuff()
{
await ThreadUtility.voidTask();
}
// Set to false when the page is unloaded (paused).
private bool m_isLoaded = false;