Create an app with a MvxFragment Fragment1 hosted by a MvxCachingFragmentCompatActivity Activity1, and a MvxFragment Fragment2 hosted by a MvxCachingFragmentCompatActivity Activity2. The fragments must have the MvxFragmentAttribute:
[MvxFragment(typeof(Activity1), Resource.Id.content_frame, true)]
[Register("example.droid.fragments.Fragment1")]
public class Fragment1 : MvxFragment<Fragment1ViewModel>
[MvxFragment(typeof(Activity2), Resource.Id.content_frame, true)]
[Register("example.droid.fragments.Fragment2")]
public class Fragment2 : MvxFragment<Fragment2ViewModel>
In the Fragment1 VM, create a command to navigate to Fragment2, using ShowViewModel<Fragment2ViewModel>(). In the Fragment2 VM, create a command to navigate to Fragment1, using ShowViewModel<Fragment1ViewModel>().
Do the following navigation:
i. open the app. The Fragment1ViewModel is shown
ii. click the button to show Fragment2ViewModel.
iii. when Fragment2ViewModel is shown, the lifecycle methods (Init, Start, etc) are called.
iv. click the button in Fragment2ViewModel to show Fragment1ViewModel again.
v. when Fragment1ViewModel is shown again, the lifecycle methods aren't called. If the steps ii through iv are repeated, the lifecycle methods of each VM aren't called again.
Expected behavior
The VM lifecycle methods (Init, Start, etc) should be called when the fragments are shown
Actual behavior
The ViewModel lifecycle methods aren't called.
Origin of the issue
From what I've seen, it seems to me that this is happening because the lifecycle methods aren't called when a cached VM is found in the OnCreate method of MvxFragmentExtensions. The lines of code in question are these:
var cache = Mvx.Resolve<IMvxMultipleViewModelCache>();
var cached = cache.GetAndClear(viewModelType, fragmentView.UniqueImmutableCacheTag);
view.OnViewCreate(() => cached ?? LoadViewModel(fragmentView, bundle, fragment.Activity.GetType(), request));
Should something like this be done instead?
var cache = Mvx.Resolve<IMvxMultipleViewModelCache>();
var cached = cache.GetAndClear(viewModelType, fragmentView.UniqueImmutableCacheTag);
view.OnViewCreate(() =>
{
if (cached != null)
{
RunViewModelLifecycle(cached, bundle, request);
return cached;
}
return LoadViewModel(fragmentView, bundle, fragment.Activity.GetType(), request);
});
I've forked the MvvmCross-AndroidSupport repository and made some changes to the sample that exemplify the behavior described in this issue. The only difference is that the navigation is done using the DrawerLayout instead of buttons on each fragment, but I believe this doesn't influence the issue. You can find my fork here.
Steps to reproduce
MvxFragment
Fragment1 hosted by aMvxCachingFragmentCompatActivity
Activity1, and aMvxFragment
Fragment2 hosted by aMvxCachingFragmentCompatActivity
Activity2. The fragments must have the MvxFragmentAttribute:ShowViewModel<Fragment2ViewModel>()
. In the Fragment2 VM, create a command to navigate to Fragment1, usingShowViewModel<Fragment1ViewModel>()
.Expected behavior
The VM lifecycle methods (Init, Start, etc) should be called when the fragments are shown
Actual behavior
The ViewModel lifecycle methods aren't called.
Origin of the issue
From what I've seen, it seems to me that this is happening because the lifecycle methods aren't called when a cached VM is found in the OnCreate method of MvxFragmentExtensions. The lines of code in question are these:
Should something like this be done instead?
I've forked the MvvmCross-AndroidSupport repository and made some changes to the sample that exemplify the behavior described in this issue. The only difference is that the navigation is done using the DrawerLayout instead of buttons on each fragment, but I believe this doesn't influence the issue. You can find my fork here.