1
votes

So I'm still new to MVVM(MvvmCross)/Android. So apologise if I'm doing something really stupid.

I've been following Stuart Lodge's on N=9 video's on "MvxGeoLocation" and "IMvxMessenger" and I'm sure I've been following it perfect, but I have no idea where I'm going wrong.

However my application is unable to resolve an interface from the constructor.

App.cs:

public override void Initialize()
{
    CreatableTypes()
        .EndingWith("Service")
        .AsInterfaces()
        .RegisterAsLazySingleton();

    RegisterAppStart<ViewModels.MainViewModel>();
}

MainViewModel.cs:

public MainViewModel(ILocationService locationService, IMvxMessenger messenger)
{
    _subscriptionToken = messenger.Subscribe<LocationMessage>(OnLocationMessage);
}

LocationService.cs:

Public class LocationService : ILocationService
{
    private readonly MvxLocationWatcher _locationWatcher;
    private readonly IMvxMessenger _messenger;

    public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)
    {
        _locationWatcher = locationWatcher;
        _messenger = messenger;
        if (!_locationWatcher.Started) _locationWatcher.Start(new MvxLocationOptions(), OnLocation, OnError);
    }

    private void OnLocation(MvxGeoLocation location)
    {
        System.Diagnostics.Debug.WriteLine(location.Coordinates.Longitude.ToString(), location.Coordinates.Latitude);
        var message = new LocationMessage(this, location.Coordinates.Longitude, location.Coordinates.Latitude);
        _messenger.Publish(message);
    }

    public void CustomLocation(double lng, double lat)
    {
        var message = new LocationMessage(this, lng, lat);
        _messenger.Publish(message);
    }

    private void OnError(MvxLocationError error)
    {
        Mvx.Error(error.Code.ToString());
    }
}

public class LocationMessage : MvxMessage
{
    public LocationMessage(object sender, double lng, double lat) : base(sender)
    {
        Lng = lng;
        Lat = lat;
    }

    public double Lng { get; private set; }
    public double Lat { get; private set; }
}

Now the ILocationService interface is empty. It's jut there for IoC reasons. Now when I run the app, it crashes on the MainView Activity on "base.OnCreate(bundle);".

Now in the override InitializeIoC method I cannot even do "Mvx.RegisterSingleton(new LocationService());" because I need to give arguments which I clearly can't. I even tried to use "Mvx.IocConstruct();", but I realised that won't work because MvvmCross does that automatically.


So the error message:

Failed to construct and initialize ViewModel for type Core.ViewModels.MainViewModel from locator MvxDefaultViewModelLocator - check InnerException for more information

InnerException:

{MvvmCross.Platform.Exceptions.MvxException: Problem creating viewModel of type MainViewModel ---> MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter locationService of type ILocationService when creating Core.ViewModels.MainViewModel at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00036] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:502 at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x0002c] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:312 at MvvmCross.Platform.Mvx.IocConstruct (System.Type t) [0x00006] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Mvx.cs:169 at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00000] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:33 --- End of inner exception stack trace --- at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x0000f] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:37 at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x0000e] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:69 }

Could provide StackTrace if needed. So what am I exactly doing wrong? I've spent so much time trying to figure this out. No clue.

Update:

Adding StackTrace (Incase it's helpful):

" at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState, MvvmCross.Core.ViewModels.IMvxViewModelLocator viewModelLocator) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:73 \n at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00020] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxViewModelLoader.cs:59 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.ViewModelFromRequest (MvvmCross.Core.ViewModels.MvxViewModelRequest viewModelRequest, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00006] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:104 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.CreateViewModelFromIntent (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00029] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:98 \n at MvvmCross.Droid.Views.MvxAndroidViewsContainer.Load (Android.Content.Intent intent, MvvmCross.Core.ViewModels.IMvxBundle savedState, System.Type viewModelTypeHint) [0x00089] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewsContainer.cs:67 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.LoadViewModel (MvvmCross.Droid.Views.IMvxAndroidView androidView, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00065] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:137 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions+<>c__DisplayClass1_0.b__1 () [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Core.Views.MvxViewExtensionMethods.OnViewCreate (MvvmCross.Core.Views.IMvxView view, System.Func1[TResult] viewModelLoader) [0x00012] in C:\\projects\\mvvmcross\\MvvmCross\\Core\\Core\\Views\\MvxViewExtensionMethods.cs:28 \n at MvvmCross.Droid.Views.MvxActivityViewExtensions.OnViewCreate (MvvmCross.Droid.Views.IMvxAndroidView androidView, Android.OS.Bundle bundle) [0x00068] in C:\\projects\\mvvmcross\\MvvmCross\\Droid\\Droid\\Views\\MvxActivityViewExtensions.cs:50 \n at MvvmCross.Droid.Views.MvxActivityAdapter.EventSourceOnCreateCalled (System.Object sender, MvvmCross.Platform.Core.MvxValueEventArgs1[T] eventArgs) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivityAdapter.cs:80 \n at (wrapper delegate-invoke) System.EventHandler1[MvvmCross.Platform.Core.MvxValueEventArgs1[Android.OS.Bundle]]:invoke_void_object_TEventArgs (object,MvvmCross.Platform.Core.MvxValueEventArgs1<Android.OS.Bundle>)\n at MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise[T] (System.EventHandler1[TEventArgs] eventHandler, System.Object sender, T value) [0x00000] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Core\MvxDelegateExtensionMethods.cs:21 \n at MvvmCross.Platform.Droid.Views.MvxEventSourceActivity.OnCreate (Android.OS.Bundle bundle) [0x00014] in C:\projects\mvvmcross\MvvmCross\Platform\Droid\Views\MvxEventSourceActivity.cs:34 \n at MvvmCross.Droid.Views.MvxActivity.OnCreate (Android.OS.Bundle bundle) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxActivity.cs:92 \n at Droid.Views.MainView.OnCreate (Android.OS.Bundle bundle) [0x00001] in /Users/jaydeephasmukhlal/Projects/LocationMessengerTest/Droid/Views/MainView.cs:13 \n at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x0000f] in :0 \n at (wrapper dynamic-method) System.Object:e63afbc8-7ae5-4091-981d-084af38f92fc (intptr,intptr,intptr)"

2

2 Answers

2
votes

You are using a concrete type in your LocationService constructor MvxLocationWatcher. This should be IMvxLocationWatcher and then the IoC will inject the concrete class based on the platform for you (Remember to install the location plugin in all platforms as well). You can check out MvvmCross Location Plugin docs for additional information.

Switch this:

public LocationService(MvxLocationWatcher locationWatcher, IMvxMessenger messenger)

to this:

public LocationService(IMvxLocationWatcher watcher, IMvxMessenger messenger)
1
votes

Ok I finally got help from my senior colleague and found out the stupid mistake I made. My interface class ILocationService was actually a class rather than an interface.

Example the ILocationService was:

public class ILocationService
{
}

Instead of:

public interface ILocationService
{
}

Therefore, changing the class to Interface solved the problem. This was the reason the it failed to initialise the ILocationService.