Improve how Forms handles Activity Restarts on Android

JohnMillerJohnMiller USForum Administrator, Xamarin Team Xamurai
edited March 16 in Xamarin.Forms Evolution

Summary

Xamarin.Forms currently is tied to the lifecycle of an the MainActivity. This means if that activity is destroyed in anyway (OS kills it, etc) the app "restarts" and offers no way to handle this behavior or restore state. This is summarized in bug #29275.

API Changes

Copying the information from the linked bug report, this is a suggestions:

Google's recommendation for this is to use a retained fragment. The activity looks for the fragment in its fragment manager when it's created, and if it doesn't find one it creates a new one. All important state is kept in the fragment, and the activity does almost nothing. That's what we need here. Instead of FormsApplicationActivity we need FormsApplicationFragment.

Intended Use Case

A common example where the current behavior is undesirable is when the app is backgrounded to the task manager. Then, some time later the user resumes from the task manager and the app restarts. That is, MainActivity.OnCreate is called again and the entire LoadApplication process happens, effectively losing any state that the user might have had in the app.

0
0 votes

Open · Last Updated

Posts

  • adamkempadamkemp USInsider, Developer Group Leader mod

    A related problem that was not considered when I filed the original bug is the scenario in which your entire application is removed from memory after a StartActivityWithResult. The sequence is this:

    1. Your app calls StartActivityWithResult to launch an activity that is in some other process.
    2. While the other activity is on the screen the system decides it needs more memory and evicts your application.
    3. The other activity finishes with a result.
    4. The system relaunches your application and then delivers the OnActivityResult call to give you the results.

    This came up in the discussion here. While the proposal in the linked thread is for Xamarin.Android (not Forms) it is still common in Forms to need to start an activity and get the results, with the camera being the most obvious example. Also, in my experience the camera is the easiest way to hit the scenario in which the application leaves memory. I remember hitting it consistently on a Nexus 9 because the camera had a high enough resolution that taking the picture and showing it on screen took up enough memory to cause Android to kick my app out of memory.

    The common problem for both Forms and for the Xamarin.Android proposal is that there is managed, in-memory state that gets lost when the application leaves memory. Using a fragment solves a similar problem with losing state that is attached to an object that is going away by moving that state to an object that can stay in memory, but if the whole app goes away then you need a more complex solution.

    The native way to handle this is to either fall back on OnSaveInstanceState and throw a bunch of state into a bundle that you can deserialize in the new process or to save the state to disk (and possibly still use the bundle just to record where you saved it). Either way you're doing serialization and deserialization, and you somehow have to figure out what state is important to save, how to save it, and (hardest) how to restore it.

    iOS has a whole complex API for state restoration that is designed for this kind of use case. iOS doesn't have quite the same problem because it doesn't rely on flows that would cause your app to leave memory for common things like using the camera, but you could still have a flow where a user wants to go to Safari or Mail and come back and find that the app lost its state. So the state restoration API allows an app to save its UI state and restore the whole UI to where you left it.

    I feel like solving a problem like this fully would require a similarly complex API in Forms for saving and restoring app state. That would be generally useful on all platforms so I think it makes sense to expose in the PCL side of the Forms API in some way.

    That said, using fragments alone would probably solve the majority of issues, and that is worth doing even without the more complex state restoration mechanism.

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    @JohnMiller It's not allways the case that you loose your app's state as all objects are still in memory when you resume an App after it was suspended with the Backbutton.
    The problem is that it runs OnCreate again without any information if the App is already in memory. Which means that it creates a new instance of your App class and runs its constructor again which can cause problems.
    Also if you have live object with references to the old App objects you can get into trouble

    this last line of the OnCreate is one of the problems IMHO

                LoadApplication(new JistTV.App ());
    
  • DennisWeluDennisWelu USUniversity, Developer Group Leader ✭✭

    Ran across this discussion searching for an answer to a custom url scheme reactivation scenario. As @ThomasBurkhart says, OnCreate is being re-run meaning all the various Init's...Forms.Init plus any kind of plugin and custom app init...are being re-executed. The Intent.Data is an indicator that the launch was due to a URL link, but what should actually be done to properly re-activate the Xamarin Forms / Android app?

Sign In or Register to comment.