JKL
JKL

Reputation: 1070

Unable to resolve instance of IMvxViewModelLoader in custom Android ViewPresenter after updating to MvvmCross 6.2.2

I made a custom Android view presenter which uses the IMvxViewModelLoader. Before updating MvvmCross from version 5.7 to 6.2.2 I used to get an instance of IMvxViewModelLoader by dependency injection:

public class CustomPresenter : MvxAndroidViewPresenter
{
    private readonly IMvxViewModelLoader _viewModelLoader;
    private readonly IFragmentTypeLookup _fragmentTypeLookup;
    private Android.Support.V4.App.FragmentManager _fragmentManager;

    public CustomPresenter(IMvxViewModelLoader viewModelLoader, IFragmentTypeLookup fragmentTypeLookup) : base(new List<Assembly>())
    {
        _fragmentTypeLookup = fragmentTypeLookup;
        _viewModelLoader = viewModelLoader;
    }

    // Other code
} 

In my Setup class which inherits from MvxAndroidSetup I override the IMvxAndroidViewPresenter CreateViewPresenter() method:

public class Setup : MvxAndroidSetup
{
    protected override IMvxApplication CreateApp()
    {
        return new App();
    }

    protected override IMvxTrace CreateDebugTrace()
    {
        return new DebugTrace();
    }

    protected override void InitializeIoC()
    {
        base.InitializeIoC();

        Mvx.RegisterSingleton<IFragmentTypeLookup>(new FragmentTypeLookup());
        Mvx.RegisterSingleton<IFileLocationService>(new FileLocationService());
        Mvx.RegisterSingleton<ISQLitePlatform>(new SQLitePlatformAndroid());
    }

    protected override IMvxAndroidViewPresenter CreateViewPresenter()
    {
        var presenter = Mvx.IocConstruct<CustomPresenter>();
        Mvx.RegisterSingleton<IMvxAndroidViewPresenter>(presenter);
        return presenter;
    }

    // Other code
}

With the update some changes had to be made to the protected override IMvxAndroidViewPresenter CreateViewPresenter() method so I changed it to:

protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
    var presenter = Mvx.IoCProvider.IoCConstruct<CustomPresenter>();
    Mvx.IoCProvider.RegisterSingleton<IMvxAndroidViewPresenter>(presenter);
    return presenter;
}

Running the app now will throw an exception inside the constructor of CustomPresenter which indicates that the IMvxViewModelLoader instance could not be resolved. I don't register it anywhere but I was assuming MvvmCross did this for me since I didn't register it anywhere before the update. More specifically I thought MvvmCross did this for me when I call base.InitializeIoC();.

I also tried to retrieve an instance of the IMvxViewModelLoader by changing the CustomPresenter constructor into:

public CustomPresenter() : base(new List<Assembly>())
{
    _fragmentTypeLookup = Mvx.IoCProvider.Resolve<IFragmentTypeLookup>();
    _viewModelLoader = Mvx.IoCProvider.Resolve<IMvxViewModelLoader>();
}

but it has the same result.

I unsuccessfully searched for clues through the update documentation: Upgrade from 5 to MvvmCross 6.

Upvotes: 1

Views: 479

Answers (1)

Cheesebaron
Cheesebaron

Reputation: 24470

IMvxViewModelLoader is created after the presenter is created. This is why you are encountering issues with resolving it when you IoC construct your presenter or when you try to resolve in the ctor of it.

What you can do is to lazy load it or get notified by the IoC that the IMvxViewModelLoader has been loaded into the IoC.

In the first case you could simply create a Property in your presenter, which checks for null when you use it:

private IMvxViewModelLoader _viewModelLoader;
private IMvxViewModelLoader ViewModelLoader
{
    get
    {
        if (_viewModelLoader == null)
            _viewModelLoader = Mvx.IoCProvider.Resolve<IMvxViewModelLoader>();

        return _viewModelLoader;
    }
}

For getting a call back when IMvxViewModelLoader is registered:

Mvx.IoCProvider.CallbackWhenRegistered<IMvxViewModelLoader>(loader =>
{
    // do your stuff here when it loads
});

Upvotes: 1

Related Questions