2010-10-12 17 views
51

Stavo guardando il modo in cui Android gestisce il cambiamento di orientamento per la mia applicazione (ho scoperto che riavvia il mainactivity sul cambiamento di orientamento. Ho visto che è possibile ignorare il metodoCome salvare lo stato durante il cambio di orientamento in Android se lo stato è fatto delle mie classi?

protected void onSaveInstanceState(Bundle outState) 

Per salvare roba, poi hanno Il problema è che ho la mia vista con oggetti personalizzati e una listview usando un adattatore personalizzato.Tutto è in un ArrayList di questi oggetti, ma ho notato che non puoi mettere oggetti arbitrari nel pacchetto! Quindi, come faccio a salvare lo stato?

risposta

36

MODIFICA: Nelle versioni più recenti di Android e con la libreria di compatibilità, retained fragments sono in genere il modo migliore per gestire il mantenimento di dati costosi da ricreare attivi attraverso la distruzione/creazione di attività. E come Dianne ha sottolineato, il mantenimento di dati non configurati era per ottimizzare cose come la generazione di miniature che sono belle da salvare per motivi di prestazioni, ma non essenziali per il funzionamento delle attività, se hanno bisogno di essere rifatte - non è un sostituto per il corretto salvataggio e ripristino dello stato di attività.

Ma indietro quando ho risposto prima questo nel 2010:
Se si desidera mantenere i propri dati (non allo stato di visualizzazione), si può effettivamente passare un oggetto arbitrario specificamente per l'orientamento modifiche utilizzando onRetainNonConfigurationInstance(). Vedi this Android Developers blog post. Basta fare attenzione a non inserire alcuna vista o altri riferimenti al contesto/attività pre-rotazione nell'oggetto che si passa, o impedirai che tali oggetti vengano raccolti e possano finire a esaurire la memoria (questo è chiamato context leak) .

+7

Nota che onRetainNonConfigurationInstance() dovrebbe * solo * essere utilizzato come ottimizzazione. La tua app dovrebbe funzionare anche se ciò non accade ... perché non c'è * nessuna * garanzia che lo farà, e in effetti molte situazioni in cui sicuramente non verrà chiamato. Per prima cosa, la tua app deve funzionare correttamente attraverso il meccanismo dello stato salvato completo e implementare questo metodo solo come ottimizzazione. – hackbod

+0

Il link sopra non è disponibile. Puoi darmi qualche altro link? – Debopam

+2

Questi metodi sono deprecati ... –

16

Innanzitutto, è necessario determinare quale sia effettivamente lo "stato" nell'app. Non hai detto cosa stai facendo in realtà, ma lascia che l'ArrayList degli oggetti sia lo stato con cui l'utente sta lavorando.

In secondo luogo, decidere quale sia effettivamente il ciclo di vita di questo stato. E 'davvero legato a quell'attività? O l'utente non dovrebbe perderlo se dice che la sua batteria si scarica, il dispositivo si spegne e successivamente torna alla tua app? Se il primo, onSaveInstanceState() è corretto; se quest'ultimo, si desidera salvare in memoria persistente in onPause().

Per onSaveInstanceState() con oggetti personalizzati, la chiave è implementare l'interfaccia Parcelable. Ciò comporta l'implementazione dei metodi su Parcelable, oltre a creare un oggetto CREATOR statico nella classe. Ecco il codice per una tipica classe Parcelable semplice:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java

Le funzioni dei tasti sono l'attuazione Parcelable:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#317

e la classe statica Creatore:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#355

(The static writeToParcel() e readFromParcel() sono solo comodità che sono state fatte per quella classe e non richieste.)

Ora che avete che, si può mettere la vostra intera ArrayList di oggetti nel Bundle stato salvato con Bundle.putParcelableArrayList:

http://developer.android.com/reference/android/os/Bundle.html#putParcelableArrayList(java.lang.String, java.util.ArrayList)

In Activity.onCreate(), controllare per vedere se si dispone di un savedState Bundle, e se quindi prova a recuperare ArrayList da quello e usalo se trovato, creando un nuovo adattatore e la visualizzazione elenco per la nuova attività che vengono utilizzati per visualizzarlo.

134

Hai provato a usare: il suo lavoro intorno,

<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/> 

nel file manifesto?

Non funziona in modo predefinito perché, quando si modifica l'orientamento, onCreate verrà richiamato e ridisegna la vista.

Se si scrive questo parametro non è necessario gestirlo in Attività, il framework si occuperà del resto delle cose. Manterrà lo stato della schermata o del layout se si modifica l'orientamento.

NOTA Se si utilizza un layout diverso per la modalità orizzontale, aggiungendo questi parametri non verrà chiamato il layout per la modalità orizzontale.

Other way e Another way

+7

+1 per screenSize! Risolto il problema per me :-) – Abdo

+3

Grazie mille, questo mi aiuterà moltissimo! – Marius

+9

Perché non funziona in modo predefinito? Chi vuole che i dati vengano persi a rotazione? – CodeSlinger512

3

ma ho notato che non si può mettere oggetti arbitrari nel pacchetto!

Per prima cosa creare gli oggetti personalizzati Parcelable.
Quindi puoi inserirli in un pacchetto.

Tutto è in un ArrayList di questi oggetti

È possibile utilizzare il metodo putParcelableArrayList in bundle per memorizzare un ArrayList di "Parcelable" oggetti personalizzati.

3

scrivi gli oggetti su stringhe JSON utilizzando Google Gson, quindi salvali come stringa. Quindi, ricostruisci le stringhe JSON salvate durante la ricostruzione dell'attività/frammento

import com.google.gson.Gson; 

public class MyClass { 
    private int a; 
    private String s; 
    private OtherSerializableClass other; 
    private List<String> list; 

    public String toJson() { 
     return new Gson().toJson(this); 
    } 

    public static ChatAPI_MessagesArray fromJson(String json){ 
     return new Gson().fromJson(json, YourClass.class); 
    } 

    // Getters 
    ... 

    // Setters 
    ... 
} 
+0

Ho molti layout, visualizzazioni testuali e pulsanti creati a livello di codice in mainactivity. La soluzione che hai fornito qui copre il mio caso o devo utilizzare un approccio diverso? Grazie – Eftekhari

Problemi correlati