Skip to content

Instance state not saved when app is killed by OS #6827

Closed

Description

@LouisCAD

What is instance state, and why it exists

On Android, an Activity can be killed at any time by the system. This happens usually when Android needs memory when your Activity is not in the foreground, or because of a non-handled configuration change, such as a locale change.
To avoid the user having to restart what he did from scratch when Android killed the Activity, the system calls onSaveInstanceState(…) when the Activity is paused, where the app is supposed to save it's data in a Bundle, and passes the saved bundle in both onCreate(…) and onRestoreInstanceState(…) when the task is resumed if the activity has been killed by the system.

The issue about it in flutter

In the flutter apps I tried (Flutter Gallery, and the base project with the FAB tap counter), if I open enough apps to make Android kill the flutter app's Activity, all the state is lost when I come back to the flutter activity (while not having remove the task from recents).

Steps to Reproduce

  1. Install Flutter Gallery
  2. Open the device's settings, and in developer options, switch "Don't keep activities" on. (see the screenshot)
    dev_option
    This will allow to simulate when Android kills Activities because it lacks memory and you're not in the foreground.
  3. Open the Flutter Gallery app and go anywhere other than the main screen.
  4. Go to the launcher by pressing the device's home button.
  5. Press the overview button and return to Flutter Gallery. Here's the bug.

What's expected: The app is in the same state that where we left off, with untouched UI.
What happens: The activity is restarted from scratch, losing all the UI state, even really really long forms.

Activity

  1. added
    engineflutter/engine related. See also e: labels.
    frameworkflutter/packages/flutter repository. See also f: labels.
    platform-androidAndroid applications specifically
    on Nov 12, 2016
  2. eseidelGoogle commented on Nov 12, 2016

    @eseidelGoogle
    Contributor

    #3427 is also likely related.

  3. LouisCAD commented on Nov 12, 2016

    @LouisCAD
    Author

    @eseidelGoogle That's right. In which format could the flutter Activity state be saved, if it can be at all as of the current version?

  4. Hixie commented on Nov 12, 2016

    @Hixie
    Contributor

    Right now we don't do anything to save anything.

    The framework itself has very little state worth saving -- it's all animation and stuff like that -- so it may be that we always leave this up to the app to do. We should probably expose it at the Dart level though. (Right now it's only exposed at the Java level.)

  5. LouisCAD commented on Nov 12, 2016

    @LouisCAD
    Author

    @Hixie On Android, all framework Views have their state automatically saved and restored by the system, which only requires the developer to save manually the non UI part of the instance state. Shouldn't flutter work the same way for all UI widgets to prevent developers from having to write all the boilerplate each time to save where the user was, the scroll position, the enabled state of some button, the state of the previous screen and so on…?

  6. Hixie commented on Nov 14, 2016

    @Hixie
    Contributor

    In Flutter, there's very little framework state to save. For example, the enabled state of a button is not state, it's input provided by the application. The current route history is stored in the framework, but not stored in a state that the framework can rebuild (since it's all instances of objects provided by the application code). The scroll position is about the only thing we could actually store (and we do save that in a store currently, just not one that survives the app).

    But in any case we should definitely do better than today.

  7. LouisCAD commented on Nov 25, 2016

    @LouisCAD
    Author

    As an experienced Android Developer, I'd like to take part to the conversation with iOS developers too when it'll be discussed so flutter can be the perfect framework to build iOS and Android apps.
    I think the persistence ability of the framework may be important to save data, preferences, cache data and states in the most developer friendly possible way.

  8. added this to the milestone on Feb 27, 2017
  9. Takhion commented on Sep 24, 2017

    @Takhion

    Whoa I didn't realise this was the case? This is actually critical, and it's worth mentioning that on devices with less memory the process could be killed quite easily!

    What about saving the PageStore (or related) as a byte stream through serialization.dart in onSaveInstanceState?

  10. LouisCAD commented on Sep 27, 2017

    @LouisCAD
    Author

    @Takhion Could you link "PageStore" you're mentioning? I'm interested in trying to workaround this issue since it seems it won't be fixed any soon (31st december of 2029 is a liiittle far IMHO)

  11. Takhion commented on Sep 27, 2017

    @Takhion

    @LouisCAD sure it's here: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/widgets/page_storage.dart

    I think you'll need to save more than that though: at least the current route(s) and maybe some state?
    What do you think @Hixie?

  12. Hixie commented on Sep 29, 2017

    @Hixie
    Contributor

    We don't currently do anything to make this easy. We haven't studied this problem in detail yet. For now I recommend storing the information you want to persist manually, and applying it afresh when the app is restored.

  13. sethladd commented on Oct 7, 2017

    @sethladd
    Contributor

    Do we expose the necessary lifecycle events ("you're about to be killed!", "congrats, you're now restored") into Dart code, so developers can handle persisting state? That seems like the sufficient capabilities to unlock devs to explore solutions. Thoughts?

  14. 141 remaining items

  15. goderbauer commented on Jun 9, 2020

    @goderbauer
    Member

    The design document with details about how to do state restoration in Flutter is available here: http://flutter.dev/go/state-restoration-design

  16. goderbauer commented on Jun 30, 2020

    @goderbauer
    Member

    The PR with the general state restoration framework as outlined in the design above has been posted: #60375. I am still working on adding some more test coverage.

  17. goderbauer commented on Jul 29, 2020

    @goderbauer
    Member

    The general state restoration framework (#60375) has been submitted. I am now working on integrating it in our widgets. Going to start with scrollables, text fields, and the Navigator.

  18. gaaclarke commented on Jul 31, 2020

    @gaaclarke
    Member

    You can implement this yourself by storing the data you want restored inside of a sqlite database. That's a technique that is used when writing servers.

    That has the benefit of restoring an app even if the battery dies on the phone or there is a kernel panic or whatever. I recommend making an OO wrapper around your SQLite calls. Dart doesn't have something like SQLite.Net which does it automatically for you unfortunately.

    edit: It's also something we did in the early days of mobile development because memory was so limited and sqlite is a great way to swap things between memory and disk.

  19. goderbauer commented on Aug 4, 2020

    @goderbauer
    Member

    I am closing this issue since the general state restoration framework (and the Android embedding) has landed. The remaining work is tracked in separate issues:

  20. luffyjie commented on Oct 12, 2020

    @luffyjie

    Well Done!!!!! Thanks flutter!!!

  21. github-actions commented on Aug 11, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  22. locked as resolved and limited conversation to collaborators on Aug 11, 2021
  23. added
    P0Critical issues such as a build break or regression
    and removed on Jun 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P0Critical issues such as a build break or regressiona: annoyanceRepeatedly frustrating issues with non-experimental functionalityc: new featureNothing broken; request for a new capabilitycustomer: crowdAffects or could affect many people, though not necessarily a specific customer.f: routesNavigator, Router, and related APIs.frameworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions