Variables membres vs setArguments dans Fragments

J’ai remarqué que dans la référence Android pour Fragments (notamment DialogFragment ), ils font deux choses différentes de ce que j’attendais:

1). Utilisez public static foo newInstance() méthode public static foo newInstance() plutôt qu’un constructeur.
2). Transmettez des valeurs à onCreateDialog en utilisant setArguments plutôt que des variables membres.

J’ai lu que newInstance semble être préférable en utilisant la reflection. Cependant, je ne comprends vraiment pas pourquoi ils passent des parameters via un bundle. J’aurais bien compris que l’utilisation de variables membres serait plus sûre (ne pas utiliser une chaîne à extraire d’une carte) et aurait moins de surcharge.

Des pensées?

Je suis également tombé sur cela et j’ai trouvé quelques avantages à utiliser les arguments Bundle sur les champs d’instance:

  • S’il se trouve dans un ensemble, le système Android le sait et peut créer et détruire votre Fragment (à l’aide du constructeur sans paramètre / par défaut obligatoire et des méthodes de cycle de vie habituelles), et renvoyer simplement le groupe d’arguments. De cette façon, aucun argument ne se perd sur une faible quantité de mémoire morte ou les changements d’orientation éventuels (cela me frappe souvent lors du premier déploiement sur un périphérique réel après le développement dans l’émulateur moins rotatif).

  • Vous pouvez simplement passer les suppléments Bundle d’une Activity en l’état à un Fragment incorporé dans la mise en page; Par exemple, je l’utilise souvent quand j’ai une Activity qui affiche un Fragment “plein écran” et qui a besoin d’un identifiant (ou d’ ContentProvider URI ContentProvider ) pour savoir quoi afficher ou faire. J’ajoute même parfois plus de choses à un Bundle (ou une copie) avant de le transmettre, par exemple

     @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) { // not a re-creation final Bundle args = new Bundle(getIntent().getExtras()); args.putInt(CoverImageFragment.BACKGROUND_RESOURCE, android.R.color.black); final Fragment fragment = CoverImageFragment.newInstance(args); getSupportFragmentManager() .beginTransaction() .add(android.R.id.content, fragment) .commit(); } } 
  • Il permet de développer un Fragment proche de celui d’une Activity , c’est-à-dire de le Bundle en «parameters d’entrée, sans exception».

En ce qui concerne les inconvénients que vous avez mentionnés:

  • Je pense que la surcharge est minime parce que vous n’allez probablement pas interroger le Bundle dans une boucle serrée, donc obtenir vos données d’argument une fois dans onCreate() , onViewCreate() , etc.

  • Pour la sécurité de type, Bundle possède toutes les différentes méthodes getXXXX() et même des surcharges pour fournir une valeur par défaut si un élément est manquant / facultatif 🙂

En ce qui concerne les méthodes newInstance() , je les considère comme un moyen simple d’encapsuler les new setArguments() et setArguments() pour mon Fragment ; Je fournis parfois un MyFragment newInstance(Ssortingng singleIdOfWhatToDisplay) qui crée à la fois le Bundle et le Fragment en même temps et renvoie une instance de Fragment prête à l’emploi.

J’ai trouvé que c’était un problème HAUTEMENT confus (l’un des nombreux problèmes qui gâchent le paysage Android).

setArguments() est une solution de contournement pour le besoin très inutile d’Android d’avoir un constructeur sans paramètre disponible pour Fragments.

Ma confusion est venue par vagues. Tout d’abord, les méthodes que vous remplacez naturellement dans votre Fragment (par exemple, onCreate , onCreateView ) reçoivent un paramètre Bundle qui représente l’ savedInstanceState d’ savedInstanceState de votre Fragment . Cet état d’instance n’a apparemment rien à voir avec les valeurs que vous stockez via setArguments() et récupérez via getArguments() . Les deux utilisent un Bundle , les deux Bundles sont susceptibles d’être accédés dans la même méthode redéfinie, ni l’un avec l’autre.

Deuxièmement, on ne sait pas comment Android utilise setArguments() . Android appelle votre constructeur sans paramètre pour reconstruire votre Fragment en rotation, mais apparemment, setArguments() méthode setArguments() plus setArguments() lors de la construction du Fragment .

Huh ????

Incroyable, mais vrai. Tout ce qui crée des setArguments() avec setArguments() existe pour compenser le besoin d’un constructeur de Fragment paramètre.

En bref, j’utilise la méthode statique newInstance pour créer mon Fragment .

 public MyFragment() { //satisfy Android } public static MyFragment newInstance(long record_id) { Log.d("MyFragment", "Putting " + record_id + " into newInstance"); MyFragment f = new MyFragment(); Bundle args = new Bundle(); args.putLong("record_id", record_id); f.setArguments(args); return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * Perform an immediate check of arguments, * which ARE NOT the same as the bundle used * for saved instance state. */ Bundle args = getArguments(); if(args != null) { record_id = args.getLong("record_id"); Log.d("MyFragment", "found record_id of " + Ssortingng.valueOf(record_id)); } if(savedInstanceState != null) { //now do something with savedInstanceState } } 

Je suis assez nouveau pour la programmation Android, mais voici ma compréhension actuelle du problème:

Le constructeur de Fragments ne peut avoir aucun paramètre. Lorsque votre activité est suspendue, votre fragment peut être libéré. Avant de reprendre votre activité, le système crée une nouvelle version de votre Fragment appelant le constructeur. Si un constructeur autre que celui par défaut est utilisé, comment Android est-il censé connaître les types et les valeurs des arguments de votre constructeur Fragments?

Je ne crois pas que ce paquet soit publié. Le bundle est conservé avec précision afin qu’il puisse être retransmis à votre fragment après avoir été recréé avec le constructeur par défaut.

Philipp Reichart y a échappé dans son post (plus que jamais éludé).

Je veux juste append un autre inconvénient aux arguments: vous devez créer dynamicment des fragments. Comme les arguments ne fonctionnent pas très bien si vous créez à partir du XML. Et je déteste vraiment ça.