54

Recentemente mi sono stancato di dover conoscere costantemente le chiavi String per passare argomenti in Bundles durante la creazione del mio Fragments. Così ho deciso di creare dei costruttori per il mio Fragments che avrebbero preso i parametri che volevo impostare e inserire queste variabili nel Bundles con le chiavi corrette String, eliminando quindi la necessità di altre Fragments e Activities che necessitassero di conoscere quelle chiavi.Creazione di un frammento: costruttore vs newInstance()

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); 
} 

E poi estraggo tali argomenti come normale.

@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]; 
    } 
} 

Tuttavia, Lint ha preso problema con questo, dicendo di non avere sottoclassi di Fragment con costruttori con altri parametri, che richiedono me di utilizzare @SuppressLint("ValidFragment") a funzionare anche l'applicazione. Il fatto è che questo codice funziona perfettamente. Posso usare ImageRotatorFragment(int imageResourceId) o il metodo old school ImageRotatorFragment() e chiamare setArguments() manualmente su di esso. Quando Android deve ricreare il frammento (modifica dell'orientamento o memoria insufficiente), chiama il costruttore ImageRotatorFragment() e quindi passa lo stesso argomento Bundle con i miei valori, che vengono impostati correttamente.

Così ho cercato l'approccio "suggerito" e vedere molti esempi utilizzando newInstance() per creare Fragments con parametri, che sembra fare la stessa cosa è il mio costruttore. Così ho fatto il mio per testarlo, e funziona perfettamente come prima, meno Lint che piagnucola.

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; 
} 

Personalmente trovo che l'utilizzo di costruttori è una pratica molto più comune di quanto fatto da usare newInstance() e passaggio di parametri. Credo che tu possa utilizzare questa stessa tecnica di costruzione con Attività e Lint non si lamenterà di ciò. Quindi la mia domanda è, perché Google non vuole che tu usi i costruttori con parametri per Fragments?

mia unica ipotesi è in modo da non provare a impostare una variabile di istanza senza utilizzare il Bundle, che non sarà possibile ottenere impostato quando il Fragment vengono ricreate. Utilizzando un metodo static newInstance(), il compilatore non ti consente di accedere a una variabile di istanza.

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

    mImageResourceId = imageResourceId; 
} 

io ancora non mi sento come questo è una ragione sufficiente per non consentire l'uso dei parametri nei costruttori. Qualcun altro ha un'idea di questo?

risposta

59

Personalmente trovo che usare i costruttori è una pratica molto più comune di sapere usare newInstance() e passare i parametri.

Il factory method pattern viene utilizzato abbastanza frequentemente nello sviluppo di software moderni.

Quindi la mia domanda è, perché Google non vuole che tu usi i costruttori con i parametri per Fragments?

È risposto alla tua domanda:

mia unica ipotesi è così non si tenta di impostare una variabile di istanza senza utilizzare il Bundle, che non sarà possibile ottenere impostare quando il frammento vengono ricreate.

Corretto.

Continuo a non ritenere che questo sia un motivo sufficiente per impedire l'utilizzo dei parametri nei costruttori.

Siete i benvenuti per la vostra opinione. Sei libero di disabilitare questo controllo di Lint, sia per costruttore che per spazio di lavoro.

0

Android ricrea solo frammenti uccide utilizzando costruttore di default, in modo che qualsiasi inizializzazione che facciamo nei costruttori aggiuntivi sarà lost.Hence i dati saranno persi.