lbugnion / sample-crossplatform-flowers

This is the "Flowers" sample that I demoed at many conferences around the world. It shows how an application can be "Truly Universal" by running on Windows 10, WPF, Xamarin.iOS, Xamarin.Android, Xamarin.Forms and more. This is also a living sample, to which I regularly add content and features.
MIT License
31 stars 16 forks source link

Android ViewModel Life Cycle #1

Open cosminstirbu opened 6 years ago

cosminstirbu commented 6 years ago

Hi Laurent,

I've been following your work on MVVM Light for a while and I'd like to thank you for your contribution to the UWP / Xamarin community.

I had a closer look at how you're using the NavigationService on Android and it's interesting that you're passing the ViewModels to the destination Activity and retrieving them using the GetAndRemoveParameter method (and it seems that you're following this pattern for iOS and UWP as well).

Since Android has a bit of complexity surrounding its Activities and Fragments lifecycle, how would you suggest handling that so that the ViewModel is kept "alive" during lifecycle events (such as configuration changes)?

Would you maybe suggest going with the Lifecycle Helpers that the Android team is introducing recently via - https://developer.android.com/topic/libraries/architecture/index.html ?

Thank you, Cosmin

BickelLukas commented 6 years ago

@cosminstirbu The way i solved this issue was: I added these 2 Methods to the implementation of the NavigationService:

public string PutParameter(object parameter)
{
    lock (_parametersByKey)
    {
        var guid = Guid.NewGuid().ToString();
        _parametersByKey.Add(guid, parameter);
        return guid;
    }
} 

public object GetAndRemoveParameter(string key)
{
    if (string.IsNullOrEmpty(key))
    {
        return null;
    }

    lock (_parametersByKey)
    {
        if (_parametersByKey.ContainsKey(key))
        {
            var param = _parametersByKey[key];
            _parametersByKey.Remove(key);
            return param;
        }

        return null;
    }
}

then I changed my Activity to:

private const string ViewModelKey = "ViewModel";

protected override void OnCreate(Bundle savedInstanceState)
{
    if (savedInstanceState != null)
        _vm = GlobalNavigation.GetAndRemoveParameter<DetailViewModel>(savedInstanceState.GetString(ViewModelKey));
    else
        _vm = GlobalNavigation.GetAndRemoveParameter<DetailViewModel>(Intent);

    ...
}

protected override void OnSaveInstanceState(Bundle outState)
{
    outState.PutString(ViewModelKey, GlobalNavigation.PutParameter(_vm));
    base.OnSaveInstanceState(outState);
}

This works like a charm without having to change anything major

cosminstirbu commented 6 years ago

@BickelLukas

Thanks for the reply.

I'm not a big fan of a static / global navigation service. I've ended up creating a PR on AndroidSupportComponents that also includes an example of how you can leverage the Android Architecture Components to use the same View Model during configuration changes.

It should get released soon and it should be available via nuget. In the meanwhile I am using my own binding library to expose it C#.

Regards, Cosmin