SaveStateToBundle and ReloadFromBundle from MvxViewModel not called

110 Views Asked by At

We have this Xamarin Forms Application. We are using MVVMCross for DependencyInjection , Navigation and more.

We now have the problem, that we can't work out, when the SaveStateToBundle and ReloadFromBundle are getting called. These methods should automatically be called, when the application goes into the tombstoning process on android, but that doesn't seem to happen.

We simulated the tombstoning by the android developer option "Don't keep activities" and also by writing a applöication, that fills a list with dummy data, until android has to clear up space and tombstones the application with mvvmcross

We are using on the Android Project MVVMCross 8.0.2 and MvvmCross.Forms 8.0.2 On the project with the viewmodels running on .NET Standard 2.1 and there we are using MVVMCross 8.0.2

We figured out, that it doesn't get called, by writing data in to the Xamarin Essentials Preferences by key and checking, if the key has the given value in it when restarting the application.

This is how we use it:

    public class LoginViewModel : ViewModelBase, IFirstViewModel
    {
        (...)

        protected override void SaveStateToBundle(IMvxBundle bundle)
        {
            Preferences.Set("testkey", "value");
            base.SaveStateToBundle(bundle);
        }

        protected override void ReloadFromBundle(IMvxBundle state)
        {
            // Returns value of key or the default value "nothing"
            Preferences.Get("testkey", "nothing");
            base.ReloadFromBundle(state);
        }

        (...)
    }

About the application setup:

  • MainActivity extends MvxFormsAppCompatActivity<Setup, App, UI.App>
[Activity(
        Label = "Mobit.MES.Client",
        Icon = "@mipmap/icon",
        Theme = "@style/MainTheme",
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize,
        LaunchMode = LaunchMode.SingleTask)]
    public class MainActivity : MvxFormsAppCompatActivity<Setup, App, UI.App>
    {

        protected override void OnCreate(Bundle bundle)
        {
            (...)

            base.OnCreate(bundle);
        }
(...)
    }
}
  • Setup from MvxFormsAndroidSetup<App, UI.App>

  • App:

public class App : MvxApplication
  {
  public override void Initialize()
  {
  // Register all Services in this assembly.
  CreatableTypes()
  .EndingWith("Service")
  .AsInterfaces()
  .RegisterAsLazySingleton();

            RegisterIoC();
      
            RegisterCustomAppStart<AppStart>();
        }
}
  • UI.App:
public partial class App : Application
  {
  public App()
  {
  InitializeComponent();
  }

  }
<?xml version="1.0" encoding="utf-8" ?> <Application xmlns="http://xamarin.com/schemas/2014/forms"              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              xmlns:controls="clr-namespace:Mobit.MES.Client.UI.Controls">     <Application.Resources>         (...)     </Application.Resources> </Application>
2

There are 2 best solutions below

1
Cheesebaron On

Looking through the 8.0.2 branch. It seems like this specific feature was never implemented for Xamarin.Forms.

To work around this, you would have to hook into the appropriate Page lifecycle events and trigger the ViewModel methods.

0
kmiterror On

I also had issues triggering tombstoning myself. "Don't keep activities" didn't work for me as well.

To actually test tombstoning on Android you have to.

  1. use SaveStateToBundle and actually save something in the bundle (if the bundle is empty ReloadFromBundle won't be called)
  2. start the app
  3. open the view which saves data to bundle
  4. push app to background
  5. call this command from CLI adb shell am kill com.example.yourappid
  6. go to task list and bring back the app

Result: ReloadFromBundle will be called

Mind that when you call adb shell am kill com.example.yourappid you will be disconnected from the debugger, this is expected behavior. If you want to debug this part, your best bet will be to use Log.Debug inside ReloadFromBundle and inspect logcat for the messages.

More details here: https://github.com/MvvmCross/MvvmCross/pull/4552/files