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?