Skip to content
This repository has been archived by the owner. It is now read-only.

Commit a992722

Browse files
committed
- Implemented Stack to track fragment tags (top most is current/last fragment)
- Inserted tracking in Show And Close methods - Implemented OnSaveInstanceState and Restore to keep Stack - ToFragment() for IMvxFragmentView to Fragments
1 parent fe3cef1 commit a992722

File tree

1 file changed

+69
-10
lines changed

1 file changed

+69
-10
lines changed

MvvmCross.Droid.Support.V7.AppCompat/MvxCachingFragmentCompatActivity.cs

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using MvvmCross.Platform;
1818
using MvvmCross.Platform.Exceptions;
1919
using MvvmCross.Platform.Platform;
20-
using MvvmCross.Binding.Droid.BindingContext;
2120
using MvvmCross.Droid.Platform;
2221
using MvvmCross.Droid.Views;
2322
using MvvmCross.Core.ViewModels;
@@ -26,6 +25,7 @@
2625
using MvvmCross.Droid.Shared.Presenter;
2726
using MvvmCross.Droid.Shared.Attributes;
2827
using MvvmCross.Droid.Shared.Fragments;
28+
using MvvmCross.Droid.Support.V4;
2929

3030
namespace MvvmCross.Droid.Support.V7.AppCompat
3131
{
@@ -34,7 +34,10 @@ public class MvxCachingFragmentCompatActivity : MvxAppCompatActivity, IFragmentC
3434
{
3535
public const string ViewModelRequestBundleKey = "__mvxViewModelRequest";
3636
private const string SavedFragmentTypesKey = "__mvxSavedFragmentTypes";
37+
private const string SavedTagBackStack = "__mvxSavedTagBackStack";
38+
3739
private IFragmentCacheConfiguration _fragmentCacheConfiguration;
40+
private readonly Stack<string> _tagBackStack = new Stack<string>();
3841

3942
public override View OnCreateView(View parent, string name, Context context, IAttributeSet attrs)
4043
{
@@ -119,6 +122,21 @@ private void RestoreFragmentsCache()
119122
}
120123
}
121124

125+
private void RestoreTagBackStackFromBundle(IMvxJsonConverter serializer, Bundle savedInstanceState)
126+
{
127+
var savedTagBackStackJson = savedInstanceState.GetString(SavedTagBackStack);
128+
if (!string.IsNullOrEmpty(savedTagBackStackJson))
129+
{
130+
var savedReversedTagBackStackState = serializer.DeserializeObject<string[]>(savedTagBackStackJson);
131+
132+
_tagBackStack.Clear();
133+
for (int i = 0; i < savedReversedTagBackStackState.Length; i++)
134+
{
135+
_tagBackStack.Push(savedReversedTagBackStackState[i]);
136+
}
137+
}
138+
}
139+
122140
private Dictionary<string, Type> CreateFragmentTypesDictionary(Bundle outState)
123141
{
124142
IMvxSavedStateConverter savedStateConverter;
@@ -157,7 +175,19 @@ protected override void OnSaveInstanceState(Bundle outState)
157175
{
158176
base.OnSaveInstanceState(outState);
159177
IMvxJsonConverter ser;
160-
if (FragmentCacheConfiguration.HasAnyFragmentsRegisteredToCache && Mvx.TryResolve(out ser))
178+
if (!Mvx.TryResolve(out ser))
179+
{
180+
return;
181+
}
182+
183+
if (_tagBackStack.Any())
184+
{
185+
var reversedTagBackStack = _tagBackStack.Reverse().ToArray();
186+
var json = ser.SerializeObject(reversedTagBackStack);
187+
outState.PutString(SavedTagBackStack, json);
188+
}
189+
190+
if (FragmentCacheConfiguration.HasAnyFragmentsRegisteredToCache)
161191
{
162192
FragmentCacheConfiguration.SaveFragmentCacheConfigurationState(outState, ser);
163193

@@ -208,9 +238,10 @@ protected virtual void ShowFragment(string tag, int contentId, Bundle bundle, bo
208238
//If we already have a previously created fragment, we only need to send the new parameters
209239
if (fragInfo.CachedFragment != null && fragmentReplaceMode == FragmentReplaceMode.ReplaceFragment)
210240
{
211-
(fragInfo.CachedFragment as Fragment).Arguments.Clear();
212-
(fragInfo.CachedFragment as Fragment).Arguments.PutAll(bundle);
213-
}
241+
var fragment = fragInfo.CachedFragment.ToFragment();
242+
fragment.Arguments.Clear();
243+
fragment.Arguments.PutAll(bundle);
244+
}
214245
else
215246
{
216247
//Otherwise, create one and cache it
@@ -222,6 +253,8 @@ protected virtual void ShowFragment(string tag, int contentId, Bundle bundle, bo
222253
currentFragment = fragInfo.CachedFragment as Fragment;
223254
ft.Replace(fragInfo.ContentId, fragInfo.CachedFragment as Fragment, fragInfo.Tag);
224255

256+
_tagBackStack.Push(fragInfo.Tag);
257+
225258
//if replacing ViewModel then clear the cache after the fragment
226259
//has been added to the transaction so that the Tag property is not null
227260
//and the UniqueImmutableCacheTag property (if not overridden) has the correct value
@@ -277,6 +310,9 @@ public override void OnBackPressed()
277310
{
278311
if (SupportFragmentManager.BackStackEntryCount >= 1)
279312
{
313+
var backStackEntry = SupportFragmentManager.GetBackStackEntryAt(SupportFragmentManager.BackStackEntryCount - 1);
314+
RemoveFromTagBackStack(backStackEntry.Name);
315+
280316
SupportFragmentManager.PopBackStackImmediate();
281317

282318
if (FragmentCacheConfiguration.EnableOnFragmentPoppedCallback)
@@ -289,6 +325,7 @@ public override void OnBackPressed()
289325
return;
290326
}
291327

328+
_tagBackStack.Clear();
292329
base.OnBackPressed();
293330
}
294331

@@ -311,12 +348,12 @@ protected virtual IEnumerable<Fragment> GetCurrentCacheableFragments()
311348

312349
protected virtual IMvxCachedFragmentInfo GetLastFragmentInfo()
313350
{
314-
var currentCacheableFragments = GetCurrentCacheableFragments().ToList();
315-
if (!currentCacheableFragments.Any())
351+
if (!_tagBackStack.Any())
352+
{
316353
throw new InvalidOperationException("Cannot retrieve last fragment as FragmentManager is empty.");
354+
}
317355

318-
var lastFragment = currentCacheableFragments.Last();
319-
var tagFragment = GetTagFromFragment(lastFragment);
356+
var tagFragment = _tagBackStack.Peek();
320357

321358
return GetFragmentInfoByTag(tagFragment);
322359
}
@@ -351,7 +388,9 @@ protected override void OnCreate (Bundle bundle)
351388
return;
352389
}
353390

354-
FragmentCacheConfiguration.RestoreCacheConfiguration(bundle, serializer);
391+
RestoreTagBackStackFromBundle(serializer, bundle);
392+
393+
FragmentCacheConfiguration.RestoreCacheConfiguration(bundle, serializer);
355394
// Gabriel has blown his trumpet. Ressurect Fragments from the dead.
356395
RestoreFragmentsCache();
357396

@@ -389,6 +428,7 @@ protected virtual void CloseFragment(string tag, int contentId)
389428
var frag = SupportFragmentManager.FindFragmentById(contentId);
390429
if (frag == null) return;
391430

431+
RemoveFromTagBackStack(frag.Tag);
392432
SupportFragmentManager.PopBackStackImmediate(tag, 1);
393433
}
394434

@@ -456,6 +496,7 @@ public virtual bool Close(IMvxViewModel viewModel)
456496
{
457497
if (SupportFragmentManager.BackStackEntryCount == 0)
458498
{
499+
_tagBackStack.Clear();
459500
base.OnBackPressed();
460501
return true;
461502
}
@@ -471,6 +512,24 @@ public virtual bool Close(IMvxViewModel viewModel)
471512
CloseFragment(frag.Tag, frag.ContentId);
472513
return true;
473514
}
515+
516+
private void RemoveFromTagBackStack(string tag)
517+
{
518+
// reverse to more logical order
519+
var tagBackStack = _tagBackStack.Reverse().ToList();
520+
521+
// remove tag
522+
var firstFoundTagIndex = tagBackStack.FindIndex(backStackTag => backStackTag == tag);
523+
if (firstFoundTagIndex > 0)
524+
tagBackStack.RemoveAt(firstFoundTagIndex);
525+
526+
// hard reset and reinitialize _tagBackStack
527+
_tagBackStack.Clear();
528+
for (var i = 0; i < tagBackStack.Count; i++)
529+
{
530+
_tagBackStack.Push(tagBackStack[i]);
531+
}
532+
}
474533
}
475534

476535
public abstract class MvxCachingFragmentCompatActivity<TViewModel>

0 commit comments

Comments
 (0)