web-dev-qa-db-fra.com

Pourquoi veux-je éviter les constructeurs autres que ceux par défaut dans les fragments?

Je crée une application avec Fragments et dans l'un d'eux, j'ai créé un constructeur autre que celui 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 suggérer comment j'accomplirais ceci:

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 autre que par défaut?

164
BlackHatSamurai

Créez un objet bundle et insérez vos données (dans cet exemple, votre objet Category). Attention, vous ne pouvez pas transmettre cet objet directement dans le bundle, à moins qu'il ne soit sérialisable. Je pense qu'il est préférable de construire votre objet dans le fragment et de ne mettre qu'un identifiant ou quelque chose d'autre dans le paquet. C'est le code pour créer et attacher un paquet:

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.

106
nistv4n

Il semble qu'aucune des réponses ne répondent réellement "pourquoi utiliser bundle pour transmettre des paramètres plutôt que des constructeurs autres que ceux par défaut"

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

Les callbacks comme onCreate ou onCreateView doivent lire les paramètres du bundle - de cette façon, vous êtes assuré de restaurer correctement l'état de fragment dans le même état que le fragment a été initialisé avec (notez que cet état peut être différent du onSaveInstanceState bundle qui est passé au onCreate/onCreateView)

La recommandation d'utiliser la méthode statique newInstance() n'est qu'une recommandation. Vous pouvez utiliser un constructeur autre que celui par défaut, mais assurez-vous de renseigner les paramètres d'initialisation dans bundle à l'intérieur du corps de ce constructeur. Et lisez ces paramètres dans les méthodes onCreate() ou onCreateView().

243
numan salati

Votre Fragment ne devrait pas avoir de constructeur à cause de la façon dont la FragmentManager l'instancie. Vous devez définir une méthode statique newInstance() statique avec les paramètres nécessaires, puis les regrouper et les définir comme arguments du fragment, auxquels vous pourrez accéder ultérieurement à l'aide du paramètre Bundle.

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 à la onCreate:

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

    //...
}

De cette façon, si l'objet est séparé et ré-attaché, l'état de l'objet peut être stocké via les arguments, un peu comme bundles attaché à Intents.

49
Asaf Pinhassi

Si vous utilisez un paramètre pour une classe. essaye ça

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

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 des arguments dans un paquet d'arguments d'un fragment), très probablement, cette règle empirique est créée pour réduire la probabilité d'oubli pour implémenter un constructeur sans argument en Java , qui n’est pas générée implicitement en présence d’une surcharge.

Dans mes projets, j'utilise Kotlin et j'implémente des fragments avec un constructeur primaire sans argument et un constructeur secondaire pour les arguments, qui ne les stocke que dans un paquet et le définit comme arguments Fragment. Tout fonctionne correctement.

1
Pavlus