1717using MvvmCross . Platform ;
1818using MvvmCross . Platform . Exceptions ;
1919using MvvmCross . Platform . Platform ;
20- using MvvmCross . Binding . Droid . BindingContext ;
2120using MvvmCross . Droid . Platform ;
2221using MvvmCross . Droid . Views ;
2322using MvvmCross . Core . ViewModels ;
2625using MvvmCross . Droid . Shared . Presenter ;
2726using MvvmCross . Droid . Shared . Attributes ;
2827using MvvmCross . Droid . Shared . Fragments ;
28+ using MvvmCross . Droid . Support . V4 ;
2929
3030namespace 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