wake-up-neo.com

Fragment erstellen: Konstruktor vs NewInstance ()

Vor kurzem war ich es leid, ständig String-Schlüssel kennen zu müssen, um beim Erstellen meiner Bundles Argumente an Fragments zu übergeben. Also entschied ich mich, Konstruktoren für meine Fragments zu erstellen, die die Parameter, die ich einstellen wollte, übernehmen und diese Variablen mit den korrekten Bundles-Schlüsseln in die String setzen, so dass andere Fragments und Activities nicht mehr benötigt werden, um diese Schlüssel zu kennen.

public ImageRotatorFragment() {
    super();
    Log.v(TAG, "ImageRotatorFragment()");
}

public ImageRotatorFragment(int imageResourceId) {
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");

    // Get arguments passed in, if any
    Bundle args = getArguments();
    if (args == null) {
        args = new Bundle();
    }
    // Add parameters to the argument bundle
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);
    setArguments(args);
}

Und dann ziehe ich diese Argumente wie gewohnt heraus.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v(TAG, "onCreate");

    // Set incoming parameters
    Bundle args = getArguments();
    if (args != null) {
        mImageResourceId = args.getInt(KEY_ARG_IMAGE_RES_ID, StaticData.getImageIds()[0]);
    }
    else {
        // Default image resource to the first image
        mImageResourceId = StaticData.getImageIds()[0];
    }
}

Lint hatte jedoch ein Problem damit und sagte, keine Unterklassen von Fragment mit Konstruktoren mit anderen Parametern zu haben, weshalb ich @SuppressLint("ValidFragment") verwenden musste, um die App sogar auszuführen. Die Sache ist, dieser Code funktioniert einwandfrei. Ich kann ImageRotatorFragment(int imageResourceId) oder die alte Schulmethode ImageRotatorFragment() verwenden und setArguments() manuell aufrufen. Wenn Android das Fragment neu erstellen muss (Orientierungsänderung oder zu wenig Arbeitsspeicher), ruft es den ImageRotatorFragment()-Konstruktor auf und übergibt dann das gleiche Argument Bundle mit meinen Werten, die korrekt festgelegt werden.

Ich habe also nach dem "vorgeschlagenen" Ansatz gesucht und sehe viele Beispiele, die newInstance() verwenden, um Fragments mit Parametern zu erstellen. Dies scheint das gleiche zu tun, was mein Konstruktor tut. Also habe ich mir ein eigenes gemacht, um es zu testen, und es funktioniert genauso einwandfrei wie zuvor, ohne dass Lint darüber jammert.

public static ImageRotatorFragment newInstance(int imageResourceId) {
    Log.v(TAG, "newInstance(int imageResourceId)");

    ImageRotatorFragment imageRotatorFragment = new ImageRotatorFragment();

    // Get arguments passed in, if any
    Bundle args = imageRotatorFragment.getArguments();
    if (args == null) {
        args = new Bundle();
    }
    // Add parameters to the argument bundle
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);
    imageRotatorFragment.setArguments(args);

    return imageRotatorFragment;
}

Ich persönlich finde, dass die Verwendung von Konstruktoren eine weitaus üblichere Praxis ist, als zu wissen, newInstance() zu verwenden und Parameter zu übergeben. Ich glaube, Sie können dieselbe Konstruktortechnik mit Aktivitäten verwenden, und Lint wird sich nicht darüber beklagen. Meine Frage ist im Grunde, warum will Google nicht, dass Sie Konstruktoren mit Parametern für Fragments verwenden?

Meine einzige Vermutung ist, dass Sie nicht versuchen, eine Instanzvariable ohne die Bundle zu setzen, die nicht gesetzt wird, wenn die Fragment neu erstellt wird. Durch die Verwendung einer static newInstance()-Methode kann der Compiler nicht auf eine Instanzvariable zugreifen. 

public ImageRotatorFragment(int imageResourceId) {
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");

    mImageResourceId = imageResourceId;
}

Ich glaube immer noch nicht, dass dies Grund genug ist, die Verwendung von Parametern in Konstruktoren zu verbieten. Hat noch jemand Einblick in das?

54
Steven Byle

Ich persönlich finde, dass die Verwendung von Konstruktoren eine weit verbreitete Praxis ist, als zu wissen, wie man newInstance () verwendet und Parameter übergibt.

Die Methode factory pattern wird in der modernen Softwareentwicklung relativ häufig verwendet.

Im Grunde ist meine Frage: Warum will Google nicht, dass Sie Konstruktoren mit Parametern für Fragmente verwenden?

Sie haben Ihre eigene Frage beantwortet:

Meine einzige Vermutung ist, dass Sie nicht versuchen, eine Instanzvariable ohne das Bundle festzulegen. Dies wird nicht festgelegt, wenn das Fragment neu erstellt wird.

Richtig.

Ich glaube immer noch nicht, dass dies Grund genug ist, die Verwendung von Parametern in Konstruktoren zu verbieten.

Sie sind zu Ihrer Meinung herzlich willkommen. Sie können diese Lint-Prüfung gerne deaktivieren, entweder auf Konstruktorebene oder pro Arbeitsbereich.

59
CommonsWare

Android stellt nur Fragmente wieder her, die mit dem Standardkonstruktor abgetötet werden. Daher gehen alle Initialisierungen in zusätzlichen Konstruktoren verloren.

0
Jatin Sachdeva