J'ai un Fragment
avec un constructeur qui prend plusieurs arguments. Mon application a bien fonctionné pendant le développement, mais en production, mes utilisateurs voient parfois ce plantage:
android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment
make sure class name exists, is public, and has an empty constructor that is public
Je pourrais créer un constructeur vide comme le suggère ce message d'erreur, mais cela n'a pas de sens pour moi car je devrais alors appeler une méthode distincte pour terminer la configuration de Fragment
.
Je suis curieux de savoir pourquoi cet accident ne se produit qu'occasionnellement. Peut-être que j'utilise ViewPager
mal? J'instancie tous les Fragment
s moi-même et les enregistre dans une liste à l'intérieur du Activity
. Je n'utilise pas de FragmentManager
transactions, car les ViewPager
exemples que j'ai vus ne l'exigeaient pas et tout semblait fonctionner pendant le développement.
la source
Fragment
sous-classe ne déclare aucun constructeur, alors par défaut un constructeur public vide sera implicitement créé pour vous (c'est un comportement Java standard ). Vous n'avez pas à déclarer explicitement un constructeur vide à moins que vous n'ayez également déclaré d'autres constructeurs (par exemple ceux avec des arguments).Réponses:
Oui, ils le font.
De toute façon, vous ne devriez pas vraiment remplacer le constructeur. Vous devez avoir une
newInstance()
méthode statique définie et passer tous les paramètres via des arguments (bundle)Par exemple:
Et bien sûr, saisir les arguments de cette façon:
Ensuite, vous instancieriez à partir de votre gestionnaire de fragments comme suit:
De cette façon, s'il est détaché et re-attaché, l'état de l'objet peut être stocké via les arguments. Tout comme les bundles attachés à Intents.
Motif - Lecture supplémentaire
J'ai pensé expliquer pourquoi les gens se demandent pourquoi.
Si vous cochez: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Fragment.java
Vous verrez la
instantiate(..)
méthode dans laFragment
classe appelle lanewInstance
méthode:http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance () Explique pourquoi, lors de l'instanciation, il vérifie que l'accesseur est
public
et que ce chargeur de classe permet d'y accéder.C'est une méthode assez méchante dans l'ensemble, mais elle permet
FragmentManger
de tuer et de recréerFragments
avec des états. (Le sous-système Android fait des choses similaires avecActivities
).Exemple de classe
On me demande beaucoup d'appeler
newInstance
. Ne confondez pas cela avec la méthode de classe. Cet exemple de classe entière doit montrer l'utilisation.la source
Comme indiqué par CommonsWare dans cette question https://stackoverflow.com/a/16064418/1319061 , cette erreur peut également se produire si vous créez une sous-classe anonyme d'un fragment, car les classes anonymes ne peuvent pas avoir de constructeurs.
Ne faites pas de sous-classes anonymes de Fragment :-)
la source
Oui, comme vous pouvez le voir, le support-package instancie également les fragments (lorsqu'ils sont détruits et rouverts). Vos
Fragment
sous-classes ont besoin d'un constructeur public vide car c'est ce que le framework appelle.la source
super()
serait inutile, car la classe parente a violé la règle du constructeur public vide. Donc non vous n'avez pas besoin de passer à l'super()
intérieur de votre constructeur.Voici ma solution simple:
1 - Définissez votre fragment
2 - Créez votre nouveau fragment et remplissez le paramètre
3 - Profitez-en!
Évidemment, vous pouvez changer le type et le nombre de paramètres. Rapide et facile.
la source