我在.NET Standard库中有一个Xamarin.Android项目,该项目具有MvvmCross 6.1.2和Resx资源(核心项目)。
tl; dr::我想在不重新启动应用程序的情况下更改应用程序设置中的语言。当前方法要求重新启动应用程序,或者由于几次切换后由于高内存使用而导致应用程序崩溃。
到目前为止,我一直在使用通过AppLanguageService
更改语言的自定义CultureInfo
。
private void ChangeLocally(string code)
{
Settings.ApplicationLanguage = code;
Strings.Culture = new CultureInfo(code);
CultureInfo.DefaultThreadCurrentUICulture = Strings.Culture;
((MvxResxTextProvider) textProvider).CurrentLanguage = Strings.Culture;
}
在我的Android布局中,我使用MvxLang
绑定来显示翻译的术语。为了在Android上更改语言,我还在Recreate()
中调用了BaseActivity
。但是,这导致了某种性能问题。切换了几种这样的语言后,该应用程序因消耗大量内存而变得异常缓慢且崩溃。似乎正在重新创建视图模型和视图,但是将旧的视图模型保留在后台。
我还尝试了在strings.xml
目录中使用values
文件的各个区域的官方方法,但是仅在Recreate()
调用或重新启动应用程序之后,语言更改才可见。 >
然后我放弃了 Recreate()
方法,而是尝试在更改语言后只是刷新 Android视图。不幸的是,这涉及几个问题:
local:MvxBind="Text Language(TextSource, 'translated_term')"
(MvxLang
仅OneTime
)RaiseAllPropertiesChanged()
中致电BaseViewModel
现在,只有重新启动应用程序后,才能以其他语言使用该应用程序。
我希望能够在不重新启动应用程序的情况下更新Android视图,或者我想使用Recreate()
调用而不会占用大量内存(例如,处置旧视图和视图模型或重新使用它们)。有什么适当的方法可以实现这一目标吗?
答案 0 :(得分:0)
您需要做的是在所有仍在运行的ViewModel上调用AutoPlugin
。这是执行此操作的一种方法:
创建一条消息,该消息将在AppLanguageService中调用ChangeLocally时广播:
RaiseAllPropertiesChanged
在BaseViewModel中订阅此消息:
public class CultureChangedMessage : MvxMessage
{
public CultureInfo CultureInfo { get; private set; }
public CultureChangedMessage(object sender, CultureInfo cultureInfo) : base(sender)
{
CultureInfo = cultureInfo;
}
}
每次在AppLanguageService中更改区域性时发布消息:
public class BaseViewModel : MvxViewModel
{
private readonly MvxSubscriptionToken _cultureChangedToken;
public BaseViewModel(IMvxMessenger messenger)
{
_cultureChangedToken = messenger.Subscribe<CultureChangedMessage>(OnCultureChanged);
}
private async void OnCultureChanged(CultureChangedMessage cultureChangedMessage)
{
await RaiseAllPropertiesChanged();
}
...
}