Várias operações do sistema Android podem afetar o estado do fragmento. Para garantir que o estado do usuário seja salvo, o framework do Android salva e restaura automaticamente os fragmentos e a pilha de retorno. Portanto, você precisa garantir que todos os dados do seu fragmento também sejam salvos e restaurados.
A tabela a seguir descreve as operações que fazem com que o fragmento perca o estado e se os vários tipos de estado persistem com essas mudanças. Os tipos de estado mencionados na tabela são os seguintes:
- Variáveis: variáveis locais no fragmento.
- Estado da visualização: qualquer dado pertencente a uma ou mais visualizações no fragmento.
- SavedState: dados inerentes a essa instância de fragmento que precisam ser salvos
em
onSaveInstanceState()
. - NonConfig: dados extraídos de uma fonte externa, como um servidor ou repositório local, ou dados criados pelo usuário que são enviados a um servidor após a confirmação.
Muitas vezes, as variáveis são tratadas da mesma forma que SavedState, mas a tabela a seguir distingue entre os dois para demonstrar o efeito das várias operações em cada um.
Operação | Variáveis | Estado da visualização | SavedState | NonConfig |
---|---|---|---|---|
Adicionado à pilha de retorno | ✓ | ✓ | x | ✓ |
Mudança de configuração | x | ✓ | ✓ | ✓ |
Interrupção/recriação de processos | x | ✓ | ✓ | ✓* |
Removido e não adicionado à backstack | x | x | x | x |
Host concluído | x | x | x | x |
* O estado NonConfig pode ser retido durante o encerramento do processo usando o módulo Saved State para ViewModel.
Tabela 1: várias operações destrutivas de fragmentos e os efeitos que elas têm em diferentes tipos de estado.
Vejamos um exemplo específico. Imagine uma tela que gera uma
string aleatória, exibindo-a em uma TextView
e oferecendo uma opção para editar
a string antes de enviá-la a um amigo:
Para esse exemplo, suponha que, quando o usuário pressionar o botão de edição, o
app exibirá uma visualização EditText
, em que o usuário poderá editar a mensagem. Se o
usuário clicar em CANCELAR, a visualização EditText
será removida, e a
visibilidade será definida como View.GONE
. Essa
tela pode exigir o gerenciamento de quatro partes de dados para garantir uma experiência
perfeita:
Dados | Tipo | Tipo de estado | Descrição |
---|---|---|---|
seed |
Long |
NonConfig | Seed usada para gerar aleatoriamente uma nova boa ação. Gerada quando
o ViewModel é criado. |
randomGoodDeed |
String |
SavedState + variável | Gerado quando o fragmento é criado pela primeira vez.
A randomGoodDeed é salva para garantir que os usuários tenham acesso à
mesma boa ação aleatória até mesmo após o encerramento e
a recriação do processo. |
isEditing |
Boolean |
SavedState + variável | Sinalização booleana definida como true quando o usuário começa a editar.
isEditing é salvo para garantir que a parte de edição
da tela permaneça visível quando o fragmento é recriado. |
Texto editado | Editable |
Estado da visualização (propriedade de EditText ) |
O texto editado na visualização EditText .
A EditText salva esse texto para garantir que as mudanças
em andamento do usuário não sejam perdidas. |
Tabela 2: determina que o app gerador de texto aleatório precisa fazer o gerenciamento.
Nas seções a seguir, descrevemos como gerenciar corretamente o estado dos seus dados usando operações destrutivas.
Estado da visualização
As visualizações são responsáveis por gerenciar os próprios estados. Por exemplo, quando uma
visualização aceita entrada do usuário, é responsabilidade dela salvar e restaurar
essa entrada para processar as mudanças de configuração. Todas as visualizações fornecidas pelo framework do Android têm a própria implementação de onSaveInstanceState()
e
onRestoreInstanceState()
. Assim, você não precisa gerenciar o estado da visualização no
seu fragmento.
Por exemplo, no cenário anterior, a string editada é mantida em um
EditText
. Um EditText
sabe
o valor do texto que está sendo exibido, bem como outros detalhes, como
o início e o fim de qualquer texto selecionado.
Uma visualização precisa de um ID para reter o estado. Esse ID precisa ser exclusivo no fragmento e na hierarquia da visualização. Visualizações sem ID não podem reter o estado.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
Como mencionado na tabela 1, as visualizações salvam e restauram ViewState
usando
todas as operações que não removem o fragmento nem destroem o host.
SavedState
Seu fragmento é responsável por gerenciar pequenas quantidades de estado dinâmico
que são essenciais para as funções do fragmento. É possível reter
dados facilmente serializados usando
Fragment.onSaveInstanceState(Bundle)
.
De modo semelhante a
Activity.onSaveInstanceState(Bundle)
,
os dados que você coloca no pacote são retidos por mudanças de configuração
e processam o encerramento e a recriação, estando disponíveis nos métodos
onCreate(Bundle)
,
onCreateView(LayoutInflater, ViewGroup, Bundle)
e
onViewCreated(View, Bundle)
do fragmento.
Continuando com o exemplo anterior, randomGoodDeed
é a ação
exibida para o usuário, enquanto isEditing
é uma sinalização para determinar se o
fragmento exibe ou oculta o EditText
. Esse estado salvo precisa ser
mantido usando onSaveInstanceState(Bundle)
, conforme mostrado no exemplo
a seguir:
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); }
Para restaurar o estado em onCreate(Bundle)
, recupere o valor armazenado
do pacote:
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 Bundle 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(); } }
Como mencionado na tabela 1, as variáveis são retidas quando o fragmento é colocado na pilha de retorno. Tratá-las como estado salvo garante que elas persistam por todas as operações destrutivas.
NonConfig
Os dados de NonConfig precisam ser colocados fora do seu fragmento, como em
um ViewModel
. No exemplo
anterior, seed
(nosso estado NonConfig) é gerado no ViewModel
.
A lógica para manter o estado pertence ao ViewModel
.
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Java
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
A classe ViewModel
permite inerentemente que os dados sobrevivam a mudanças de
configuração, como rotações de tela, e permaneçam na memória quando o
fragmento é colocado na pilha de retorno. Após o encerramento e a recriação do processo,
o ViewModel
é recriado, e uma nova seed
é gerada. A adição de um
módulo SavedState
ao ViewModel
permite que o ViewModel
retenha o estado simples após o
encerramento e a recriação do processo.
Outros recursos
Para ver mais informações sobre como gerenciar o estado de fragmentos, consulte os recursos a seguir.