SaveStateToBundle 和 ReloadFromBundle 在 MvxViewModel 中没有被调用。

huangapple go评论80阅读模式
英文:

SaveStateToBundle and ReloadFromBundle from MvxViewModel not called

问题

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 application, 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>
英文:

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(&quot;testkey&quot;, &quot;value&quot;);
            base.SaveStateToBundle(bundle);
        }

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

        (...)
    }

About the application setup:

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

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

            base.OnCreate(bundle);
        }
(...)
    }
}
  • Setup from MvxFormsAndroidSetup&lt;App, UI.App&gt;

  • App:

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

            RegisterIoC();
      
            RegisterCustomAppStart&lt;AppStart&gt;();
        }
}
  • UI.App:
public partial class App : Application
  {
  public App()
  {
  InitializeComponent();
  }

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

答案1

得分: 1

在查看 8.0.2 分支时,似乎这个特定功能从未在 Xamarin.Forms 中实现。

要解决此问题,您需要连接到适当的页面生命周期事件并触发 ViewModel 方法。

英文:

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.

答案2

得分: 0

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

英文:

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

huangapple
  • 本文由 发表于 2023年5月22日 15:52:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304045.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定