174 votes

Pourquoi vouloir éviter les constructeurs par défaut dans les fragments ?

Je crée une application avec Fragments et dans l'un d'eux, j'ai créé un constructeur par défaut et j'ai reçu cet avertissement :

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

Quelqu'un peut-il me dire pourquoi ce n'est pas une bonne idée ?

Pouvez-vous également me suggérer la manière dont je pourrais accomplir cette tâche ?

public static class MenuFragment extends ListFragment {
    public ListView listView1;
    Categories category;

    //this is my "non-default" constructor
    public MenuFragment(Categories category){
        this.category = category;
    }....

Sans utiliser le constructeur par défaut ?

3 votes

Non, ça n'aide pas. Ils n'ont pas répondu à ma question. Mais merci quand même :)

35 votes

@BlaineOmega En fait, celui-ci en particulier : stackoverflow.com/a/11602478/321697 répond définitivement à votre question. Lors d'un changement d'orientation ou d'un autre événement qui entraîne la recréation du fragment, Android utilise le constructeur par défaut ainsi que le Bundle passé en argument. Si vous utilisez un constructeur personnalisé, dès que le fragment est recréé suite à l'un de ces événements, tout ce que vous avez fait dans le constructeur personnalisé est perdu.

278voto

numan salati Points 4684

Il semble qu'aucune des réponses ne réponde réellement à la question "pourquoi utiliser le bundle pour passer des paramètres plutôt que des constructeurs non par défaut".

La raison pour laquelle vous devez passer des paramètres par le biais de bundle est que lorsque le système restaure une fragment (par exemple lors d'un changement de configuration), il restaurera automatiquement votre bundle .

Les rappels comme onCreate o onCreateView doit lire les paramètres de l'élément bundle - de cette façon, vous avez la garantie de restaurer l'état de la fragment correctement au même état que le fragment a été initialisée (notez que cet état peut être différent de l'état de la onSaveInstanceState bundle qui est transmis à la onCreate/onCreateView )

La recommandation d'utiliser la méthode statique newInstance() Cette méthode n'est qu'une recommandation. Vous pouvez utiliser un constructeur qui n'est pas par défaut, mais assurez-vous de remplir les paramètres d'initialisation dans le fichier de configuration. bundle à l'intérieur du corps de ce constructeur. Et lire ces paramètres dans le onCreate() o onCreateView() méthodes.

2 votes

Bien expliqué. Merci. Si c'était moi qui avais posé la question, je vous aurais donné une coche.

5 votes

Il n'est plus possible d'utiliser un constructeur autre que celui par défaut (pour quelque raison que ce soit) ...., ce qui entraîne une erreur de compilation (auparavant, il s'agissait d'un avertissement).

112voto

nistv4n Points 606

Créez un objet bundle et insérez vos données (dans cet exemple votre Category objet). Attention, vous ne pouvez pas passer cet objet directement dans le bundle, sauf s'il est sérialisable. Je pense qu'il est préférable de construire votre objet dans le fragment, et de mettre seulement un id ou autre chose dans le bundle. Voici le code pour créer et attacher un bundle :

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);

Après cela, dans vos données d'accès aux fragments :

Type value = getArguments().getType("key");

C'est tout.

3 votes

Comment passer un objet ? Je veux passer un objet contextuel ou tout autre objet.

12 votes

Les bundles peuvent transporter des objets Java sérialisés ainsi que des objets de type Parcelable objets. De même, vous ne devez pas passer un Context parce que cette information est accessible par le biais de l'attribut [getActivity() méthode](http://developer.android.com/reference/android/app/Fragment.html#getActivity()) .

0 votes

Dans le fragment où il faut le faire Type value = getArguments().getType("key"); ?

52voto

Pinhassi Points 4297

Votre Fragment ne devraient pas avoir de constructeurs à cause de la façon dont le FragmentManager l'instancie. Vous devriez avoir un newInstance() définie avec les paramètres dont vous avez besoin, puis les regrouper et les définir en tant qu'arguments du fragment, auquel vous pourrez accéder ultérieurement avec la méthode Bundle paramètre.

Par exemple :

public static MyFragment newInstance(int title, String message) {
    MyFragment fragment = new MyFragment();
    Bundle bundle = new Bundle(2);
    bundle.putInt(EXTRA_TITLE, title);
    bundle.putString(EXTRA_MESSAGE, message);
    fragment.setArguments(bundle);
    return fragment ;
}

Et lisez ces arguments à onCreate :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    title = getArguments().getInt(EXTRA_TITLE);
    message = getArguments().getString(EXTRA_MESSAGE);

    //...
}

De cette façon, en cas de détachement et de ré-attachement, l'état de l'objet peut être stocké à travers les arguments, un peu comme dans le cas de bundles attaché à Intent s.

9voto

김동기 Points 203

Si vous utilisez un paramètre pour une classe, essayez ceci

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}

1voto

Pavlus Points 702

Je pense qu'il n'y a pas de différence entre un constructeur statique et deux constructeurs (un vide et un paramétré qui stocke les arguments dans le paquet d'arguments d'un fragment), très probablement, cette règle empirique est créée pour réduire la probabilité d'oublier d'implémenter un constructeur sans argument en Java, qui n'est pas implicitement généré lorsque la surcharge est présente.

Dans mes projets, j'utilise Kotlin, et j'implémente les fragments avec un constructeur primaire sans argument et un constructeur secondaire pour les arguments qui les stocke simplement dans un paquet et le définit comme arguments de fragment, tout fonctionne bien.

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