Xamarin MvvmCross:iOS 如何监控应用程序已移至 foreground/background
Xamarin MvvmCross: iOS how to monitor the app has move to foreground/background
我有一个 MvvmCross 应用程序,我正在使用 MvvmCross ViewModel Lifecycle 函数来实现
视图出现、移动到背景和移动到前景时的某些操作:
- public 覆盖 async void ViewAppeared()
- public 覆盖 async void ViewAppearing()
- public 覆盖 void ViewDisappearing()
- public 覆盖 void ViewDisappeared()
- public 覆盖 void ViewDestroy(bool viewFinishing)
这些功能在我的 Android 设备上运行良好。
但是对于 iOS 它们不会在应用程序移动到后台或前台时被触发
(虽然,除了 ViewDestroy,它们在 iOS 中的应用程序的屏幕之间导航时触发)
1)这是预期的行为,还是我遗漏了什么?
2)如果是这样,当应用程序移动到 foreground/background 时我们需要执行哪些操作(例如停止计时器),我们必须遵循什么方法?
我们是否应该有两种实现方式,一种用于 android,另一种用于 ios?我还尝试了 MvxBaseViewController 中的 ViewDidDisappear 方法,
当应用程序移至后台时,它仍未激活。 Xamarin/MvvmCross 中有一种方法可以挂接到本机 ios applicationDidEnterBackground?
编辑:
我试过 Ranjit 的回答,但订阅消息似乎有问题。这是我的测试代码:
AppDelegate.cs:
public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
var message = new LocationMessage(
this,
34
);
_messenger = Mvx.IoCProvider.Resolve<IMvxMessenger>();
_messenger.Publish(message);
}
基础class:
public abstract class GenericMvxViewModel : MvxViewModel
{
private IMvxMessenger _messenger;
protected GenericMvxViewModel()
{
// other stuff
_messenger = Mvx.IoCProvider.Resolve<IMvxMessenger>();
_messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
protected virtual void OnLocationMessage(LocationMessage locationMessage){}
}
视图模型:
public class MyClassViewModel : GenericMvxViewModel
{
protected override void OnLocationMessage(LocationMessage locationMessage)
{
Debug.WriteLine(locationMessage.Lat);
}
}
消息在 AppDelegate.cs 中发布,但从未执行视图模型中的 OnLocationMessage 方法。
我也想知道如何正确取消订阅消息。 ViewDestroy 似乎是最自然的地方,但如前所述,它从未在 iOS
上被调用
您的代码应该可以工作。我在我的应用程序中使用了相同类型的功能,它工作正常
GenericMvxViewModel 代码
private MvxSubscriptionToken _locationEventToken;
public override void ViewAppeared()
{
SubscribeBaseLocationEvent();
base.ViewAppeared();
}
public override void ViewDisappeared()
{
if (StaticStorage.IsApplicationInForeground)
{
UnSubscribeBaseLocationEvent();
}
base.ViewDisappeared();
}
public void SubscribeBaseLocationEvent()
{
if (_locationEventToken == null)
{
_locationEventToken = Messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
}
public void UnSubscribeBaseLocationEvent()
{
if (_locationEventToken != null)
{
Messenger.Unsubscribe<LocationMessage>(_locationEventToken);
_locationEventToken = null;
}
}
AppDelegate 代码
public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
StaticStorage.IsApplicationInForeground = false;
_messenger.Publish(new LocationMessage( this, 34 ));
}
public override void WillEnterForeground(UIApplication application)
{
StaticStorage.IsApplicationInForeground = true;
}
Android
protected override void OnResume()
{
StaticStorage.IsApplicationInForeground = true;
base.OnResume();
}
protected override void OnStop()
{
StaticStorage.IsApplicationInForeground = false;
base.OnStart();
}
当应用程序从一个视图移动到另一个视图时,我们需要取消订阅该事件。但不是当应用程序移动到后台时。因此,IsApplicationInForeground 标志将有助于解决 android 的这个问题。因为对于 android 当应用程序进入后台时 ViewDisappeared 将被调用。
以我为例。我有一个常见的 activity,它包含片段的剩余所有视图。所以,我添加了这个共同的代码activity。不确定您的情况如何使用。但实施将是相似的。
我有一个 MvvmCross 应用程序,我正在使用 MvvmCross ViewModel Lifecycle 函数来实现 视图出现、移动到背景和移动到前景时的某些操作:
- public 覆盖 async void ViewAppeared()
- public 覆盖 async void ViewAppearing()
- public 覆盖 void ViewDisappearing()
- public 覆盖 void ViewDisappeared()
- public 覆盖 void ViewDestroy(bool viewFinishing)
这些功能在我的 Android 设备上运行良好。 但是对于 iOS 它们不会在应用程序移动到后台或前台时被触发 (虽然,除了 ViewDestroy,它们在 iOS 中的应用程序的屏幕之间导航时触发)
1)这是预期的行为,还是我遗漏了什么?
2)如果是这样,当应用程序移动到 foreground/background 时我们需要执行哪些操作(例如停止计时器),我们必须遵循什么方法? 我们是否应该有两种实现方式,一种用于 android,另一种用于 ios?我还尝试了 MvxBaseViewController 中的 ViewDidDisappear 方法, 当应用程序移至后台时,它仍未激活。 Xamarin/MvvmCross 中有一种方法可以挂接到本机 ios applicationDidEnterBackground?
编辑: 我试过 Ranjit 的回答,但订阅消息似乎有问题。这是我的测试代码:
AppDelegate.cs:
public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
var message = new LocationMessage(
this,
34
);
_messenger = Mvx.IoCProvider.Resolve<IMvxMessenger>();
_messenger.Publish(message);
}
基础class:
public abstract class GenericMvxViewModel : MvxViewModel
{
private IMvxMessenger _messenger;
protected GenericMvxViewModel()
{
// other stuff
_messenger = Mvx.IoCProvider.Resolve<IMvxMessenger>();
_messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
protected virtual void OnLocationMessage(LocationMessage locationMessage){}
}
视图模型:
public class MyClassViewModel : GenericMvxViewModel
{
protected override void OnLocationMessage(LocationMessage locationMessage)
{
Debug.WriteLine(locationMessage.Lat);
}
}
消息在 AppDelegate.cs 中发布,但从未执行视图模型中的 OnLocationMessage 方法。
我也想知道如何正确取消订阅消息。 ViewDestroy 似乎是最自然的地方,但如前所述,它从未在 iOS
上被调用您的代码应该可以工作。我在我的应用程序中使用了相同类型的功能,它工作正常
GenericMvxViewModel 代码
private MvxSubscriptionToken _locationEventToken;
public override void ViewAppeared()
{
SubscribeBaseLocationEvent();
base.ViewAppeared();
}
public override void ViewDisappeared()
{
if (StaticStorage.IsApplicationInForeground)
{
UnSubscribeBaseLocationEvent();
}
base.ViewDisappeared();
}
public void SubscribeBaseLocationEvent()
{
if (_locationEventToken == null)
{
_locationEventToken = Messenger.Subscribe<LocationMessage>(OnLocationMessage);
}
}
public void UnSubscribeBaseLocationEvent()
{
if (_locationEventToken != null)
{
Messenger.Unsubscribe<LocationMessage>(_locationEventToken);
_locationEventToken = null;
}
}
AppDelegate 代码
public override void DidEnterBackground(UIApplication application)
{
base.DidEnterBackground(application);
StaticStorage.IsApplicationInForeground = false;
_messenger.Publish(new LocationMessage( this, 34 ));
}
public override void WillEnterForeground(UIApplication application)
{
StaticStorage.IsApplicationInForeground = true;
}
Android
protected override void OnResume()
{
StaticStorage.IsApplicationInForeground = true;
base.OnResume();
}
protected override void OnStop()
{
StaticStorage.IsApplicationInForeground = false;
base.OnStart();
}
当应用程序从一个视图移动到另一个视图时,我们需要取消订阅该事件。但不是当应用程序移动到后台时。因此,IsApplicationInForeground 标志将有助于解决 android 的这个问题。因为对于 android 当应用程序进入后台时 ViewDisappeared 将被调用。
以我为例。我有一个常见的 activity,它包含片段的剩余所有视图。所以,我添加了这个共同的代码activity。不确定您的情况如何使用。但实施将是相似的。