Ligeira variação na minha outra postagem
Basicamente, tenho uma mensagem Handler
na minha Fragment
que recebe um monte de mensagens que podem resultar em caixas de diálogo sendo descartadas ou exibidas.
Quando o aplicativo é colocado em segundo plano, recebo um, onPause
mas ainda recebo minhas mensagens como esperado. No entanto, como estou usando fragmentos, não posso simplesmente descartar e mostrar os diálogos, pois isso resultará em um IllegalStateException
.
Não posso simplesmente dispensar ou cancelar a perda de estado.
Visto que tenho um Handler
, estou me perguntando se há uma abordagem recomendada sobre como devo lidar com as mensagens em um estado de pausa.
Uma possível solução que estou considerando é gravar as mensagens que chegam durante a pausa e reproduzi-las em um onResume
. Isso é um tanto insatisfatório e estou pensando que deve haver algo na estrutura para lidar com isso de forma mais elegante.
Respostas:
Embora o sistema operacional Android não pareça ter um mecanismo que resolva suficientemente o seu problema, acredito que esse padrão oferece uma solução alternativa relativamente simples de implementar.
A classe a seguir é um wrapper
android.os.Handler
que armazena mensagens quando uma atividade é pausada e as reproduz na continuação.Certifique-se de que qualquer código que você tenha, que muda de forma assíncrona um estado de fragmento (por exemplo, confirmar, rejeitar), seja chamado apenas de uma mensagem no manipulador.
Derive seu manipulador da
PauseHandler
classe.Sempre que sua atividade recebe uma
onPause()
chamadaPauseHandler.pause()
e paraonResume()
chamadaPauseHandler.resume()
.Substitua sua implementação do Handler
handleMessage()
porprocessMessage()
.Fornece uma implementação simples da
storeMessage()
qual sempre retornatrue
.Abaixo está um exemplo simples de como a
PausedHandler
classe pode ser usada.Com o clique de um botão, uma mensagem atrasada é enviada ao manipulador.
Quando o manipulador recebe a mensagem (no thread de IU), ele exibe um
DialogFragment
.Se a
PausedHandler
classe não estivesse sendo usada, uma IllegalStateException seria mostrada se o botão home fosse pressionado após pressionar o botão de teste para iniciar o diálogo.Eu adicionei um
storeMessage()
método àPausedHandler
classe no caso de qualquer mensagem deve ser processada imediatamente, mesmo quando a atividade está pausada. Se uma mensagem for tratada, false deve ser retornado e a mensagem será descartada.fonte
resume
método usasendMessage(msg)
tecnicamente, pode haver outros threads enfileirando a mensagem logo antes (ou entre as iterações do loop), o que significa que as mensagens armazenadas podem ser intercaladas com a chegada de novas mensagens. Não tenho certeza se é um grande negócio. Talvez usarsendMessageAtFrontOfQueue
(e é claro iterar para trás) resolveria esse problema?Uma versão um pouco mais simples do excelente PauseHandler do quickdraw é
Ele supõe que você sempre deseja armazenar mensagens offline para reprodução. E fornece a Activity como entrada para
#processMessages
que você não precise gerenciá-la na subclasse.fonte
resume()
epause()
, ehandleMessage
synchronized
?Aqui está uma maneira ligeiramente diferente de abordar o problema de fazer commits de Fragment em uma função de retorno de chamada e evitar o problema IllegalStateException.
Primeiro crie uma interface executável personalizada.
Em seguida, crie um fragmento para processar os objetos MyRunnable. Se o objeto MyRunnable foi criado depois que a Activity foi pausada, por exemplo, se a tela foi girada, ou o usuário pressionou o botão home, ele é colocado em uma fila para processamento posterior com um novo contexto. A fila sobrevive a quaisquer alterações de configuração porque a instância setRetain está definida como verdadeira. O método runProtected é executado no thread da IU para evitar uma condição de corrida com o sinalizador isPaused.
Finalmente, o fragmento pode ser usado em um aplicativo principal da seguinte maneira:
fonte
Em meus projetos, uso o padrão de design do observador para resolver isso. No Android, broadcast receivers e intents são uma implementação desse padrão.
O que eu faço é criar um BroadcastReceiver que me registrar no compartimento do fragmento / atividade onResume e cancelar o registro no compartimento do fragmento / atividade onPause . Em BroadcastReceiver método de OnReceive eu coloquei todo o código que precisa ser executado como resultado de - a BroadcastReceiver - receber uma Intenção (mensagem) que foi enviado para o seu aplicativo em geral. Para aumentar a seletividade sobre o tipo de intents que seu fragmento pode receber, você pode usar um filtro de intent como no exemplo abaixo.
Uma vantagem dessa abordagem é que o Intent (mensagem) pode ser enviado de qualquer lugar dentro do seu aplicativo (uma caixa de diálogo aberta no topo do seu fragmento, uma tarefa assíncrona, outro fragmento etc.). Os parâmetros podem até ser passados como extras de intent.
Outra vantagem é que essa abordagem é compatível com qualquer versão da API do Android, uma vez que BroadcastReceivers e Intents foram introduzidos na API de nível 1.
Você não é obrigado a configurar nenhuma permissão especial no arquivo de manifesto do seu aplicativo, exceto se você planeja usar sendStickyBroadcast (onde você precisa adicionar BROADCAST_STICKY).
fonte