2013-08-15 13 views
27

Conosco il "newInstance" -Pattern (Best practice for instantiating a new Android Fragment). Ma come faccio ad aggiornare questi argomenti di un frammento, ad esempio se un altro frammento modifica i dati?Le migliori pratiche per l'aggiornamento degli argomenti di un frammento?

Conosco i metodi di callback tra Fragments/Activitys, ma questi callback non aggiornano gli argomenti ?!

Ad esempio: durante la creazione del frammento, passo un URI al gruppo con il pacchetto. Quindi un altro frammento modifica questo URI tramite la callback del metodo changeUri (Uri uri) sul primo frammento. Se poi il frammento viene ricreato (ad esempio a causa della rotazione dello schermo) userà il primo URI dal bundle di argomenti invece del uri aggiornato successivamente, corretto?

Qual è la migliore pratica per risolvere questo? Devo memorizzarlo manualmente in savedInstanceState e al momento dell'utilizzo decidere se utilizzare instanceState o arguments-bundle?

Sto cercando un modo standard di gestire gli argomenti dei miei frammenti, quindi penso che sto andando con questo tipo di approccio (pseudo-codice):

private Uri arg1; 

public static Fragment newInstance(Uri arg1) { 
    create bundle 
    create fragment instance 
    set bundle to fragment 
    return fragment 
} 

private void onCreate(Bundle savedInstance) { 
    if(savedInstance != null) { 
    arg1 = savedInstance.uri 
    } 
} 

private Uri getUri() { 
    if(arg1 == null) { 
    arg1 = getArguments.uri 
    } 
    if(arg1 == null) { 
    arg1 = defaultValue 
    } 
} 

Così ho un semplicemente unificato modo per accedere alla mia discussione. E non devi usare il fastidio se-else, ogni volta che ho bisogno di quell'argomento.

Cosa ne pensi?

+0

Sì. Di che codice sta parlando? Un metodo oveeriden -'onSaveInstanceState'- con 1 riga in più e un'istruzione if-else in 'onCreate'? – gunar

+0

I frammenti dei difetti di progettazione fallita non dovrebbero dipendere da altri frammenti – danny117

+0

Che dire di "riscrivere" gli argomenti in un metodo pubblico di quel frammento? –

risposta

16

Non è possibile modificare gli argomenti una volta impostato e Fragment aggiunto a Activity, ho utilizzato un approccio simile definito dall'utente. Per prima cosa ho controllato il Bundle passato a onCreate() se non è nullo lo uso ma se è nullo, allora uso gli argomenti. E salvo qualunque sia il più nuovo dato in onSaveInstanceState(). Per ulteriori dettagli: Is it possible to pass arguments to a fragment after it's been added to an activity?

+1

Consiglio vivamente di impostare questa opzione come risposta per dare il giusto credito. –

4

Si salva lo stato nello stesso modo in cui si farebbe per le attività nella callback del frammento onSaveInstanceState. Se l'URI è stato aggiornato dall'ultimo onCreate(), l'URI aggiornato verrà archiviato nello Bundle e verrà restituito in onCreate(). Lo stato di salvataggio è esattamente ciò per cui è stato progettato e, modificando l'URI, tutto ciò che hai fatto è stato cambiato stato.

0

A seconda del modo in cui si utilizzano i frammenti, è possibile determinare l'efficacia di tale strategia.

Ad esempio, se si dispone di molti frammenti nella scheda comune/visualizzazione del modello di cercapersone e li si sta gestendo con FragmentStatePagerAdapter potrebbe esserci l'opportunità per l'attività o altri frammenti di fare riferimento a un'istanza di frammento che non esiste più causando un null eccezione puntatore.

Un modo per aggirare questo problema, se non si desidera scrivere callback, è utilizzare Intents e BroadcastReceivers (che può essere un po 'eccessivo e difficile da gestire, ma se fatto correttamente può risparmiare un sacco di mal di testa nella mia esperienza) per inviare e ricevere trasmissioni da e verso l'attività principale.

La cosa bella di intents è che possono essere sintonizzati per funzionare in momenti specifici e accettare una vasta gamma di extra di dati, inclusi bundle e oggetti parcel-able.

1

Best practice for updating arguments of a fragment: perché abbiamo bisogno di aggiungere argomentazione NewInstance() metodo & perché è best practice per frammento?

Il frammento può essere considerato come una sezione modulare di un'attività. Ciò significa che quando creiamo un frammento, dobbiamo renderlo modulare & indipendente.

Supponiamo avete bisogno di un frammento, che hanno bisogno di un argomento per operate.We può anche scriverlo

MyFragmentClass mFrag = new MyFragmentClass(); 
Bundle bundle = new Bundle(); 
bundle.putString("key", value); 
mFrag.setArguments(bundle); 

Funziona anche bene & è possibile ottenere argomento onCreate metodo. Ecco la differenza che puoi anche creare un'istanza di frammento senza argomento e aggiungerla al gestore di frammenti, ma il tuo frammento ha bisogno di argomenti per funzionare. L'aggiunta del metodo newInstance nel frammento costringe lo sviluppatore a aggiungere argomenti durante la creazione. Ecco perché si dice che le migliori pratiche.

Nel tuo problema puoi usare setRetainInstance(boolean retain) che impedisce al tuo frammento di non distruggere quando l'attività viene distrutta.

4

mi limito a cambiare il valore in bundle Esempio:

synchronized (fragment.getArguments()) { 
     fragment.getArguments().putInt(KEY, new Value); 
    } 

e aggiornamento dei contenuti con il nuovo argomento

+3

Perché sincronizzato? –

+0

sì, perché sincronizzato usato? –

0

Incase si vuole riutilizzare un frammento, ma necessità di aggiornare gli argomenti, è necessario utilizzare fragment.getArguments(). PutAll (bundle);

private static void setInspireByDoArguments(DoOptionsFragment fragment, long doId) { 
    Bundle bundle = new Bundle(); 
    bundle.putLong(Constants.EXTRA_DO_ID, doId); 
    bundle.putInt(Constants.EXTRA_DO_OPTIONS_DIALOG_MODE, MODE_GET_INSPIRE_BY_DO); 
    if (fragment.getArguments() != null) { 
     fragment.getArguments().putAll(bundle); 
    } else 
     fragment.setArguments(bundle); 
} 

//This is how I managed to Check if the fragment exist and update the arguments. 

public static void showDoInspireDialog(FragmentManager fragmentManager, long doId, DoOptionsFragment.DoOptionCallBack callBack) { 
    DoOptionsFragment doOptionsFragment = (DoOptionsFragment) fragmentManager.findFragmentByTag("do_options_fragment"); 
    if (doOptionsFragment == null) { 
     doOptionsFragment = DoOptionsFragment.getInspiredByDoInstance(doId, callBack); 
     fragmentManager.beginTransaction() 
       .add(doOptionsFragment, "do_options_fragment") 
       .commit(); 
    } else { 
     doOptionsFragment.setCallBack(callBack); 
     setInspireByDoArguments(doOptionsFragment, doId); 
     doOptionsFragment.showInspireByDoDialog(doId); 
    } 
} 

    public static DoOptionsFragment getInspiredByDoInstance(long doId, DoOptionsFragment.DoOptionCallBack callBack) { 
    DoOptionsFragment doOptionsFragment = new DoOptionsFragment(); 
    setInspireByDoArguments(doOptionsFragment, doId); 
    doOptionsFragment.setCallBack(callBack); 
    return doOptionsFragment; 
} 
+0

'fragment.setArguments (bundle)' può produrre 'java.lang.IllegalStateException' se si ritorna al frammento esistente in Activity – StAlex

Problemi correlati