775 votes

Meilleure pratique pour l'instanciation d'un nouveau fragment d'Android

J'ai vu deux pratiques générales pour instancier un nouveau Fragment dans une application :

Fragment newFragment = new MyFragment();

y

Fragment newFragment = MyFragment.newInstance();

La deuxième option fait appel à une méthode statique newInstance() y généralement contient la méthode suivante.

public static Fragment newInstance() 
{
    MyFragment myFragment = new MyFragment();
    return myFragment;
}

Au début, je pensais que le principal avantage était le fait que je pouvais surcharger la méthode newInstance() afin de donner de la flexibilité lors de la création de nouvelles instances d'un Fragment - mais je pouvais aussi le faire en créant un constructeur surchargé pour le Fragment.

J'ai raté quelque chose ?

Quels sont les avantages d'une approche par rapport à une autre ? Ou s'agit-il simplement d'une bonne pratique ?

0 votes

Lorsqu'il y a des paramètres, il n'y a pas de choix, et cette question est largement traitée ici. Cependant, la question reste posée pour la construction sans argument du fragment.

1 votes

Après avoir appris le factory pattern et comment une classe appelante qui n'instancie pas elle-même un objet aide à les découpler, j'ai pensé que ce serait un point fort pour la méthode newInstance(). Ai-je tort ? Je n'ai pas vu cet argument spécifique parlé comme un avantage.

21voto

Ilya_Gazman Points 3685

I ne pas être d'accord avec yydi réponse en disant :

Si Android décide de recréer votre Fra le constructeur sans argument de votre fragment. Donc surcharger le constructeur n'est pas une solution.

Je pense que c'est une solution et une bonne solution, c'est exactement la raison pour laquelle elle a été développée par le langage de base Java.

Il est vrai que le système Android peut détruire et recréer votre Fragment . Donc vous pouvez faire ça :

public MyFragment() {
//  An empty constructor for Android System to use, otherwise exception may occur.
}

public MyFragment(int someInt) {
    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    setArguments(args);
}

Il vous permettra de tirer someInt de getArguments() plus tard, même si le Fragment a été recréé par le système. Cette solution est plus élégante que static constructeur.

A mon avis static sont inutiles et ne devraient pas être utilisés. De plus, ils vous limiteront si, à l'avenir, vous souhaitez étendre ce programme. Fragment et ajouter plus de fonctionnalités au constructeur. Avec static vous ne pouvez pas le faire.

Mise à jour :

Android a ajouté une inspection qui signale tous les constructeurs non par défaut par une erreur.
Je recommande de le désactiver, pour les raisons mentionnées ci-dessus.

5 votes

Un autre avantage d'avoir une méthode statique, que je n'ai pas mentionné ci-dessus, est que vous ne pouvez pas accidentellement définir des propriétés à partir de celle-ci.

5 votes

De plus, en ce qui concerne votre point sur "étendre ce fragment", cette méthode serait en fait très mauvaise si vous étendez un jour la classe. L'appel à super fera que l'appel setArguments() ne sera effectif que pour l'enfant ou le parent, mais pas les deux !

0 votes

Cela dépend du moment où vous appelez super(...) dans l'implémentation de l'enfant, mais le point essentiel est que setArguments() ne fonctionne que pour le dernier paquet défini.

5voto

vhfree Points 11

Je suis là depuis peu. Mais je viens de découvrir des choses qui pourraient vous aider un peu.

Si vous utilisez Java, il n'y a pas grand-chose à changer. Mais pour les développeurs Kotlin, voici quelques extraits qui, je pense, peuvent faire de vous un sous-sol sur lequel courir :

  • Fragment parental :

    inline fun <reified T : SampleFragment> newInstance(text: String): T { return T::class.java.newInstance().apply { arguments = Bundle().also { it.putString("key_text_arg", text) } } }

  • Appel normal

    val f: SampleFragment = SampleFragment.newInstance("ABC") // or val f = SampleFragment.newInstance<SampleFragment>("ABC")

  • Vous pouvez étendre l'opération parent init dans la classe de fragment enfant par :

    fun newInstance(): ChildSampleFragment { val child = UserProfileFragment.newInstance<ChildSampleFragment>("XYZ") // Do anything with the current initialized args bundle here // with child.arguments = .... return child }

Bon codage.

3voto

Gunhan Points 375

La meilleure pratique pour les fragments d'instance avec des arguments dans Android est d'avoir une méthode de fabrique statique dans votre fragment.

public static MyFragment newInstance(String name, int age) {
    Bundle bundle = new Bundle();
    bundle.putString("name", name);
    bundle.putInt("age", age);

    MyFragment fragment = new MyFragment();
    fragment.setArguments(bundle);

    return fragment;
}

Vous devez éviter de définir vos champs avec l'instance d'un fragment. Parce que chaque fois que le système Android recrée votre fragment, s'il estime que le système a besoin de plus de mémoire, il recréera votre fragment en utilisant le constructeur sans arguments.

Vous pouvez trouver plus d'informations sur meilleure pratique pour instancier les fragments avec des arguments ici.

2voto

Tigra Points 1134

Puisque les questions sur les meilleures pratiques, je voudrais ajouter, que très souvent une bonne idée d'utiliser l'approche hybride pour la création de fragment quand on travaille avec certains services web REST.

Nous ne pouvons pas passer des objets complexes, par exemple un modèle d'utilisateur, dans le cas de l'affichage d'un fragment d'utilisateur.

Mais ce que nous pouvons faire, c'est de vérifier onCreate que l'utilisateur!=null et si non - alors le faire venir de la couche de données, sinon - utiliser l'existant.

De cette façon, nous obtenons à la fois la capacité de recréer par userId en cas de recréation de fragment par Android et la rapidité des actions de l'utilisateur, ainsi que la capacité de créer des fragments en maintenant l'objet lui-même ou seulement son id.

Quelque chose comme ça :

public class UserFragment extends Fragment {
    public final static String USER_ID="user_id";
    private User user;
    private long userId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userId = getArguments().getLong(USER_ID);
        if(user==null){
            //
            // Recreating here user from user id(i.e requesting from your data model,
            // which could be services, direct request to rest, or data layer sitting
            // on application model
            //
             user = bringUser();
        }
    }

    public static UserFragment newInstance(User user, long user_id){
        UserFragment userFragment = new UserFragment();
        Bundle args = new Bundle();
        args.putLong(USER_ID,user_id);
        if(user!=null){
            userFragment.user=user;
        }
        userFragment.setArguments(args);
        return userFragment;

    }

    public static UserFragment newInstance(long user_id){
        return newInstance(null,user_id);
    }

    public static UserFragment newInstance(User user){
        return newInstance(user,user.id);
    }
}

1voto

Amin Emadi Points 11

Utilisez ce code pour résoudre à 100% votre problème

saisissez ce code dans premierFragment

public static yourNameParentFragment newInstance() {

    Bundle args = new Bundle();
    args.putBoolean("yourKey",yourValue);
    YourFragment fragment = new YourFragment();
    fragment.setArguments(args);
    return fragment;
}

cet échantillon envoie des données booléennes

et en SecendFragment

yourNameParentFragment name =yourNameParentFragment.newInstance();
   Bundle bundle;
   bundle=sellDiamondFragments2.getArguments();
  boolean a= bundle.getBoolean("yourKey");

doit la valeur dans le premier fragment est statique

code de bonheur

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