【问题标题】:MvvmCross - instantiate ViewModel with activity (context) parameterMvvmCross - 使用活动(上下文)参数实例化 ViewModel
【发布时间】:2017-10-18 11:54:50
【问题描述】:

使用 MvvmCross,我创建了一种跨平台方法来翻译 Android 和 iOS 上的字符串,因此我可以在我的 ViewModel 中使用一个共享的 translate() 方法。我在我的核心项目中有一个共享接口ILocalizationHelper,在每个平台中我都创建了一个从接口继承的LocalizationHelper 类。所以我的ViewModel 现在包含一个ILocalizationHelper 实例,我可以在该实例上使用我的translate() 方法。

问题:要在Android 上使用GetString() 翻译字符串,我需要一个上下文(Activity)。所以实例化这个LocalizationHelper 并不简单。目前我使用MvxViewModel 中的Translator 属性解决了这个问题,我可以从我的视图中设置。

我的Fragment类如下:

[MvxFragment(typeof(AccountViewModel), Resource.Id.content_frame, AddToBackStack = true)]
[Register("appname.Android.Fragments.Account.LoginFragment")]
public class LoginFragment : MvxFragment<LoginViewModel>
{
    base.OnCreateView(inflater, container, savedInstanceState);
    View view = this.BindingInflate(Resource.Layout.FragmentLogin, container, false);

    ViewModel.Translator = new LocalizationHelper(Activity);
}

现在我在想这可能是不好的做法(是吗?)。所以我更喜欢使用 ViewModel 的构造函数注入我的 LocalizationHelper 实例。但我不知道我怎么能做到这一点,如果它甚至可能的话:

private ILocalizationHelper _translator;

public ILocalizationHelper Translator
{
    get { return _translator; }
    set { _translator = value; }
}    

public LoginViewModel(ILocalizationHelper localizationHelper)
{
    _translator = localizationHelper;
}

感谢您对与此相关的最佳实践的任何启发。

【问题讨论】:

    标签: c# android xamarin mvvm mvvmcross


    【解决方案1】:

    您可以使用在当前顶部Activity 注册的IMvxAndroidCurrentTopActivity 在您的android LocalizationHelper 实现中获取活动上下文。

    var context = Mvx.Resolve&lt;IMvxAndroidCurrentTopActivity&gt;().Activity;

    【讨论】:

    • 谢谢,我发现了 IMvxAndroidCurrentTopActivity 但不知道它可以在哪里使用。 VS 之前也不允许我导入它,因为我在错误的方法/类中使用了它。您的解决方案也解决了我的问题,但是因为我认为我的类是全局的,所以我更喜欢使用应用程序上下文方法。谢谢! :)
    【解决方案2】:

    Context 应该在初始化LocalizationHelper 时设置。我假设这可以被视为一个单例,所以最好的地方是你的 Android 项目中的 Setup 类。

    覆盖 InitializeFirstChance() 并将单例注册到 Mvx IoC。然后,您将能够在 ViewModel 中使用构造函数注入。

    由于上下文已经被单例捕获,您的 ViewModel 不必担心它。这就是插件的工作原理(尽管 Mvx 具有插件的自动注册功能)。

    public class Setup : MvxAndroidSetup
    {
        private readonly Context _applicationContext;
    
        public Setup(Context applicationContext) : base(applicationContext)
        {
            // save copy of application context
            _applicationContext = applicationContext;
        }
    
        protected override void InitializeFirstChance()
        {
            base.InitializeFirstChance();
    
            // instantiate and register helper
            Mvx.RegisterSingleton<ILocalizationHelper>(new LocalizationHelper(_applicationContext));
        }
    }
    
    
    public class MyViewModel : MvxViewModel
    {
        private readonly ILocalizationHelper _localizationHelper;
    
        // constructor injector of helper singleton
        public MyViewModel(ILocalizationHelper localizationHelper)
        {
            _localizationHelper = localizationHelper;
    
            // you will now be able to use _localizationHelper from the rest of the ViewModel
        }
    
    }
    

    【讨论】:

    • 感谢您的详细解释。我现在明白它是如何工作的 :)
    【解决方案3】:

    您可以在 DependencyContainer 中注册 ApplicationContext 并将其注入到您的 LocalizationHelper 实现中。

    如果您必须使用当前的活动上下文,您可以将其注册为 Func&lt;Context&gt;(并在每次调用 Translate 时解决它),或者按照 @Plac3Hold3r 的建议将 IMvxAndroidCurrentTopActivity 注入到您的 LocalizationHelper 实现中.

    【讨论】:

    • 通过“在 DependencyContainer 中注册”,您可能是指 Mvx.Register...() 对,就像@Kiliman 的回答一样?还是有其他方法?感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多