31 votes

Une navigation cassée sur JellyBean?

Le code Source est disponible ici: https://github.com/novemberox/NavigationTest C'est une version modifiée de cet exemple: http://developer.android.com/training/implementing-navigation/ancestral.html

J'ai trois activités:

  • Main Activity juste à l'entrée principale de l'application
  • Category Activity il est parent pour le Détail de l'Activité
  • Detail Activity

Main Activity a bouton qui ouvre Category Activity et Detail Activity. Category Activty a juste un bouton qui ouvre Detail Activity. Et enfin Detail Activity qui affiche du texte et a bouton qui simule cliquez sur ActionBar jusqu'.

Mon "en cliquant sur" chemin d'accès est:

  • ouvrir l'Activité Principale
  • ouvrir le Détail de l'Activité
  • cliquez sur "bouton"
  • Catégorie de l'Activité devrait apparaître
  • retour sur nous déplace l'Activité Principale de l'état restauré

Et c'est le débit qui serait attend, et il fonctionne très bien sur tous les Androïde avant de Jelly Bean (testé sur Galaxy Nexus 4.1.1 et l'émulateur 4.2 Google exp pack). Il fonctionne même sur ICS. Je suis d'utilisation d'un support lib et les classes comme NavUtils et TaskStackBuilder, comme dans l'exemple que j'ai fait au début.

Sur JB lorsque je clique sur le "bouton", il va revenir à l'Activité Principale de l'état restauré correctement. J'ai regardé dans le code source de la bibliothèque de prise en charge et j'ai vu qu' NavUtils.navigateUpTo des appels de méthode native JB code comme celui - Activity#navigateUpTo. J'ai essayé les deux, NavUtils#navigateUpTo() et NavUtils.navigateUpFromSameTask() avec le même résultat insatisfaisant.

Avez-vous des suggestions à faire pour avoir ce débit agréable?

63voto

cyfur01 Points 1215

Tout d'abord, si vous êtes ciblage des dispositifs aussi haut que l'API 17 (Android 4.2), à l'ensemble de l' targetSdkVersion - 17 dans votre manifeste. Cela ne veut pas briser le support pour les anciens appareils, il rend juste les choses fonctionnent correctement pour les appareils récents. Bien sûr, cela ne résout pas votre problème, c'est juste bon de le faire.

Que Devriez-Vous Utiliser?

Je suppose que vous basez votre code de la Ancestraux de Navigation exemple sur cette page. Vous avez utilisé le second exemple:

Intent upIntent = new Intent(this, MyParentActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
    // This activity is not part of the application's task, so create a new task
    // with a synthesized back stack.
    TaskStackBuilder.from(this)
        .addNextIntent(new Intent(this, MyGreatGrandParentActivity.class))
        .addNextIntent(new Intent(this, MyGrandParentActivity.class))
        .addNextIntent(upIntent)
        .startActivities();
    finish();
 } else {
     // This activity is part of the application's task, so simply
     // navigate up to the hierarchical parent activity.
     NavUtils.navigateUpTo(this, upIntent);
 }

Pour le comportement que vous voulez, cependant, vous avez besoin de remplacer NavUtils.navigateUpTo avec:

upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(upIntent);
finish();

Pourquoi faut-il travailler sur ICS et plus Tôt?

En général, le soutien de la bibliothèque est d'essayer d' approximatif, le comportement introduit plus tard dans les Api. Dans le cas d' NavUtils, la bibliothèque de prise en charge est d'essayer de rapprocher le comportement introduit dans l'API 16 (un.k.un. Android 4.1). Pour le pré-API 16 plates-formes, NavUtils utilise:

@Override
public void navigateUpTo(Activity activity, Intent upIntent) {
    upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    activity.startActivity(upIntent);
    activity.finish();
}

Cela ressemble à travers la pile de retour pour une instance de l'activité indiquée en upInent. Si il en trouve un, il efface tout jusqu'à elle et la restaure. Sinon il vient de lance de l'activité.

Sur API+ de 16 ans plus tard, les plates-formes, le soutien de la bibliothèque mains des choses hors de l'appel des indigènes dans l' Activity API. Selon les docs:

public boolean navigateUpTo (Intention upIntent)

Naviguer à partir de cette activité à l'activité visée par upIntent, la finition de cette activité dans le processus. Si l'activité indiquée par upIntent existe déjà dans la tâche de l'histoire, de cette activité et tous les autres avant que l'indication de l'activité dans l'histoire de la pile sera fini.

Si indiqué, l'activité n'apparaît pas dans l'histoire de la pile, ce sera la fin de chaque activité dans cette tâche jusqu'à la racine des activités de la tâche est atteint, ce qui entraîne une "in-app "maison" de comportement. Cela peut être utile dans des applications avec une navigation complexe hiérarchie lorsqu'une activité ne peut être atteint par un chemin ne passant pas par le biais d'un canoniques activité parent.

À part cela, il est difficile de savoir si ou non il va lancer l'activité indiquée en upIntent si elle n'est pas dans la pile de retour. La lecture du code source n'aide pas à clarifier les choses non plus. Toutefois, à en juger par le comportement de votre application est de montrer, il semble qu'il n'a pas de tentative de lancement de l' upIntent de l'activité.

Indépendamment de la mise en œuvre est bon ou mauvais, le résultat final est que vous voulez l' FLAG_ACTIVITY_CLEAR_TOP comportement, pas l'API native 16 comportement. Malheureusement, cela signifie que vous devrez reproduire le soutien de la bibliothèque de rapprochement.

Ce qui est Correct?

Avertissement: je ne travaille pas pour Google, donc c'est ma meilleure supposition.

Ma conjecture est que l'API 16+ comportement est le comportement voulu; c'est une interface de mise en œuvre qui a accès à l'Android internes et peuvent faire des choses qui ne sont pas possible par le biais de l'API. Pré-API 16, je ne pense pas qu'il était possible de se détendre la backstack dans ce mode d'autres, que par l'intention de drapeaux. Ainsi, l' FLAG_ACTIVITY_CLEAR_TOP drapeau est l' approximation la plus proche de l'API 16 comportement disponible à la pré-API 16 plates-formes.

Malheureusement, le résultat est que, entre le maternelle la mise en œuvre et la bibliothèque de prise en charge de la mise en œuvre il y a une violation du principe de moindre étonnement dans votre scénario. Ce qui m'amène à me demander si c'est un imprévu utilisation de l'API. I. e., Je me demande si Android s'attend à ce que vous avez à traverser toute la chemin de navigation pour une activité, de ne pas sauter directement à elle.

Juste au Cas où

Juste pour éviter un possible malentendu, il est possible que quelqu'un pourrait s'attendre à ce shouldUpRecreateTask grâce à la magie de déterminer que le parent n'est pas dans la pile de retour et passer par le processus de la synthèse de tout pour vous à l'aide de l' TaskStackBuilder.

Toutefois, shouldUpRecreateTask détermine fondamentalement si votre activité est lancé directement par votre application (dans ce cas, il renvoie false), ou si elle a été lancée à partir d'une autre application (dans ce cas, il renvoie true). À partir de ce livre, la bibliothèque de prise en charge vérifie si l'intention est "action" n'est pas ACTION_MAIN (je ne comprends pas tout ça), alors que sur l'API 16 plates-formes de il effectue ce test basé sur la tâche de l'affinité. Encore, dans le cas de cette application, les choses fonctionnent à l' shouldUpRecreateTask retourner false.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X