使用MvvmCross

时间:2019-02-05 19:38:15

标签: android xamarin xamarin.android internationalization mvvmcross

我在.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视图。不幸的是,这涉及几个问题:

  • 我必须用更一般的绑定替换MvxLang绑定才能更新属性更改,即local:MvxBind="Text Language(TextSource, 'translated_term')"MvxLangOneTime
  • 我不得不在RaiseAllPropertiesChanged()中致电BaseViewModel
  • 仍然仅更新当前活动,例如标签栏以及其他活动和片段仍保留以前的语言

现在,只有重新启动应用程序后,才能以其他语言使用该应用程序。

我想拥有的东西

我希望能够在不重新启动应用程序的情况下更新Android视图,或者我想使用Recreate()调用而不会占用大量内存(例如,处置旧视图和视图模型或重新使用它们)。有什么适当的方法可以实现这一目标吗?

1 个答案:

答案 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();
    }
    ...
}