Same Activity Repeats Again on Backpress in Android
Various Android system operations tin affect the country of your fragment. To ensure the user's state is saved, the Android framework automatically saves and restores the fragments and the back stack. Therefore, you need to ensure that any data in your fragment is saved and restored as well.
The following table outlines the operations that crusade your fragment to lose land, forth with whether the various types of land persist through those changes. The state types mentioned in the table are as follows:
- Variables: local variables in the fragment.
- View State: any information that is owned by one or more views in the fragment.
- SavedState: information inherent to this fragment case that should be saved in
onSaveInstanceState()
. - NonConfig: data pulled from an external source, such equally a server or local repository, or user-created data that is sent to a server once committed.
Oftentimes Variables are treated the aforementioned every bit SavedState, only the following table distinguishes betwixt the two to demonstrate the consequence of the various operations on each.
Operation | Variables | View State | SavedState | NonConfig |
---|---|---|---|---|
Added to back stack | ✓ | ✓ | x | ✓ |
Config Change | ten | ✓ | ✓ | ✓ |
Process Death/Recreation | x | ✓ | ✓ | ✓* |
Removed non added to back stack | ten | x | x | x |
Host finished | ten | x | x | ten |
* NonConfig country tin can be retained across process expiry using the Saved State module for ViewModel.
Table 1: Various fragment subversive operations and the effects they have on different state types.
Let's look at a specific example. Consider a screen that generates a random string, displays information technology in a TextView
, and provides an pick to edit the cord before sending it to a friend:

For this example, assume that once the user presses the edit button, the app displays an EditText
view where the user can edit the bulletin. If the user clicks on Cancel, the EditText
view should be cleared and it'south visibility set to View.GONE
. Such a screen might require managing iv pieces of information to ensure a seamless experience:
Data | Type | State type | Clarification |
---|---|---|---|
seed | Long | NonConfig | Seed used for randomly generating a new skilful deed. Generated when the ViewModel is created. |
randomGoodDeed | String | SavedState + Variable | Generated when the fragment is created for the very get-go fourth dimension. randomGoodDeed is saved to ensure that users see the same random expert deed even after process death and recreation. |
isEditing | Boolean | SavedState + Variable | Boolean flag set to true when the user begins editing. isEditing is saved to ensure that the editing portion of the screen remains visible when the fragment is recreated. |
Edited text | Editable | View Land (endemic by EditText ) | The edited text in the EditText view. The EditText view saves this text to ensure that the user's in-progress changes are not lost. |
Table 2: States that the random text generator app must manage.
The following sections describe how to properly manage the state of your information through destructive operations.
View country
Views are responsible for managing their own country. For example, when a view accepts user input, information technology is the view's responsibleness to relieve and restore that input to handle configuration changes. All Android framework-provided views have their own implementation of onSaveInstanceState()
and onRestoreInstanceState()
, so you lot don't take to manage view country within your fragment.
For case, in the previous scenario, the edited string is held in an EditText
. An EditText
knows the value of the text it's displaying, as well as other details, such as the beginning and terminate of any selected text.
A view needs an ID to retain its country. This ID must be unique inside the fragment and its view bureaucracy. Views without an ID cannot retain their state.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
As mentioned in table 1, views save and restore their ViewState
through all operations that don't remove the fragment or destroy the host.
SavedState
Your fragment is responsible for managing small amounts of dynamic state that are integral to how the fragment functions. Yous can retain hands-serialized data using Fragment.onSaveInstanceState(Bundle)
. Similar to Activity.onSaveInstanceState(Bundle)
, the information you place in the bundle is retained through configuration changes and process expiry and recreation and is bachelor in your fragment'southward onCreate(Bundle)
, onCreateView(LayoutInflater, ViewGroup, Package)
, and onViewCreated(View, Bundle)
methods.
Tip: When using a ViewModel
, you tin save state direct within the ViewModel
using a SavedStateHandle
. For more information, encounter Saved State module for ViewModel.
Continuing with the previous example, randomGoodDeed
is the deed that'south displayed to the user, and isEditing
is a flag to decide whether the fragment shows or hides the EditText
. This saved state should be persisted using onSaveInstanceState(Bundle)
, as shown in the post-obit instance:
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Java
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
To restore the state in onCreate(Bundle)
retrieve the stored value from the parcel:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Java
@Override public void onCreate(@Nullable Package savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
Every bit mentioned in table 1, note that the variables are retained when the fragment is placed on the backstack. Treating them as saved state ensures they persist through all destructive operations.
NonConfig
NonConfig data should be placed outside of your fragment, such equally in a ViewModel
. In the previous example to a higher place, seed
(our NonConfig state) is generated in the ViewModel
. The logic to maintain its state is owned past the ViewModel
.
Kotlin
public course RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good act using the seed return goodDeed } }
Coffee
public form RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed individual String generateRandomGoodDeed() { Cord goodDeed = ... // Generate a random practiced deed using the seed render goodDeed; } }
The ViewModel
form inherently allows data to survive configuration changes, such as screen rotations, and remains in retentiveness when the fragment is placed on the back stack. Later on process death and recreation, the ViewModel
is recreated, and a new seed
is generated. Adding a SavedState
module to your ViewModel
allows the ViewModel
to retain simple state through process death and recreation.
Additional resources
For more than data about managing fragment state, see the following additional resources.
Codelabs
- Lifecycle-Aware Components codelab
Guides
- Saved State Module for View Model
- Saving UI States
Source: https://developer.android.com/guide/fragments/saving-state
0 Response to "Same Activity Repeats Again on Backpress in Android"
Post a Comment