Légère variation sur mon autre message
Fondamentalement, j'ai un message Handler
dans mon Fragment
qui reçoit un tas de messages qui peuvent entraîner le rejet ou l'affichage des boîtes de dialogue.
Lorsque l'application est mise en arrière-plan, je reçois un onPause
message mais je reçois toujours mes messages comme prévu. Cependant, comme j'utilise des fragments, je ne peux pas simplement ignorer et afficher les boîtes de dialogue car cela entraînera un fichier IllegalStateException
.
Je ne peux pas simplement rejeter ou annuler l'autorisation de la perte d'état.
Étant donné que j'ai un, Handler
je me demande s'il existe une approche recommandée pour savoir comment gérer les messages en état de pause.
Une solution possible que j'envisage est d'enregistrer les messages qui arrivent pendant une pause et de les lire sur un fichier onResume
. C'est quelque peu insatisfaisant et je pense qu'il doit y avoir quelque chose dans le cadre pour gérer cela de manière plus élégante.
Réponses:
Bien que le système d'exploitation Android ne semble pas avoir de mécanisme qui résout suffisamment votre problème, je pense que ce modèle fournit une solution de contournement relativement simple à mettre en œuvre.
La classe suivante est un wrapper
android.os.Handler
qui met en mémoire tampon les messages lorsqu'une activité est suspendue et les lit à la reprise.Assurez-vous que tout code dont vous disposez qui modifie de manière asynchrone un état de fragment (par exemple, validation, rejet) n'est appelé qu'à partir d'un message dans le gestionnaire.
Dérivez votre gestionnaire de la
PauseHandler
classe.Chaque fois que votre activité reçoit un
onPause()
appelPauseHandler.pause()
et pouronResume()
appelPauseHandler.resume()
.Remplacez votre implémentation du gestionnaire
handleMessage()
parprocessMessage()
.Fournir une implémentation simple
storeMessage()
qui revient toujourstrue
.Voici un exemple simple de la façon dont la
PausedHandler
classe peut être utilisée.En cliquant sur un bouton, un message différé est envoyé au gestionnaire.
Lorsque le gestionnaire reçoit le message (sur le thread d'interface utilisateur), il affiche un fichier
DialogFragment
.Si la
PausedHandler
classe n'était pas utilisée, une exception IllegalStateException serait affichée si le bouton d'accueil était pressé après avoir appuyé sur le bouton de test pour lancer la boîte de dialogue.J'ai ajouté une
storeMessage()
méthode à laPausedHandler
classe au cas où des messages devraient être traités immédiatement, même lorsque l'activité est en pause. Si un message est traité, false doit être renvoyé et le message sera rejeté.la source
resume
méthode utilisesendMessage(msg)
techniquement il pourrait y avoir d'autres threads mettant en file d'attente le message juste avant (ou entre les itérations de la boucle), ce qui signifie que les messages stockés pourraient être entrelacés avec de nouveaux messages arrivant. Je ne sais pas si c'est un gros problème. Peut-être que l'utilisationsendMessageAtFrontOfQueue
(et bien sûr l'itération vers l'arrière) résoudrait ce problème?Une version légèrement plus simple de l'excellent PauseHandler de quickdraw est
Cela suppose que vous souhaitez toujours stocker les messages hors ligne pour la relecture. Et fournit l'activité comme entrée pour
#processMessages
que vous n'ayez pas besoin de la gérer dans la sous-classe.la source
resume()
etpause()
, ethandleMessage
synchronized
?Voici une manière légèrement différente d'aborder le problème des validations de Fragment dans une fonction de rappel et d'éviter le problème IllegalStateException.
Créez d'abord une interface exécutable personnalisée.
Ensuite, créez un fragment pour traiter les objets MyRunnable. Si l'objet MyRunnable a été créé après la mise en pause de l'activité, par exemple si l'écran pivote ou si l'utilisateur appuie sur le bouton d'accueil, il est placé dans une file d'attente pour un traitement ultérieur avec un nouveau contexte. La file d'attente survit à toutes les modifications de configuration car l'instance setRetain est définie sur true. La méthode runProtected s'exécute sur le thread d'interface utilisateur pour éviter une condition de concurrence avec l'indicateur isPaused.
Enfin, le fragment peut être utilisé dans une application principale comme suit:
la source
Dans mes projets, j'utilise le modèle de conception d'observateur pour résoudre ce problème. Dans Android, les récepteurs de diffusion et les intentions sont une implémentation de ce modèle.
Ce que je fais est de créer un BroadcastReceiver que j'inscrire dans du fragment de / activité onResume désinscriptions dans du fragment de / activité OnPause . Dans BroadcastReceiver méthode de OnReceive je mets tout le code qui a besoin pour fonctionner en raison de - la BroadcastReceiver - réception d' une intention (message) qui a été envoyé à votre application en général. Pour augmenter la sélectivité sur le type d'intents que votre fragment peut recevoir, vous pouvez utiliser un filtre d'intention comme dans l'exemple ci-dessous.
Un avantage de cette approche est que l' intention (message) peut être envoyée de partout dans votre application (une boîte de dialogue qui s'est ouverte au-dessus de votre fragment, une tâche asynchrone, un autre fragment, etc.). Les paramètres peuvent même être passés comme extras d'intention.
Un autre avantage est que cette approche est compatible avec n'importe quelle version d'API Android, puisque BroadcastReceivers et Intents ont été introduits au niveau d'API 1.
Vous n'êtes pas obligé de configurer des autorisations spéciales sur le fichier manifeste de votre application, sauf si vous prévoyez d'utiliser sendStickyBroadcast (où vous devez ajouter BROADCAST_STICKY).
la source