2010-07-29 16 views
15

Mi piacerebbe che Attività sullo stack Attività della mia applicazione abbia solo un'istanza. Ho diverse schermate che sono ListActivities e mi piacerebbe non passare attraverso il dolore e la sofferenza dell'aggiornamento degli elenchi in un'istanza precedente di ListActivity quando viene modificata un'altra istanza di ListActivity (aggiunta, modificata, rimossa da, ecc.) (o c'è un modo semplice per farlo?).startActivityForResult non funziona correttamente con launchMode singleInstance

Nota: ho letto che singleTop lo farà (anche se distrugge l'attività se si preme il pulsante indietro), ma non funziona. Ho un menu e se vado nella schermata Posta in arrivo, vado alla schermata QuickList, quindi vado di nuovo nella schermata Posta in arrivo, crea una nuova Attività Posta in arrivo.

In questo momento, sul mio ListActivities, ho launchMode impostato su singleInstance. Il problema è: se lancio un'altra attività utilizzando startActivityForResult, il gestore onActivityResult si attiva immediatamente (prima che venga creata la nuova attività). Quando eseguo l'azione necessaria nella schermata successiva per restituire il risultato, il gestore onActivityResult non viene attivato.

Cosa sta succedendo?

Ecco come mi licenzio la nuova attività:

Intent intentLaunchQuickList = new Intent(ActivityMyList.this, ActivityQuickList.class); 
startActivityForResult(intentLaunchQuickList, REQUEST_QUICKLIST); 

Ecco come torno il risultato:

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 
    super.onListItemClick(l, v, position, id); 
    QuickListItem qlItem = m_Adapter.getItem(position); 
    if (qlItem != null && qlItem.getQLId() != -1) { 
     Intent data = new Intent(); 
     data.putExtra("ql_id", qlItem.getQLId()); 
     if (getParent() == null) { 
      setResult(Activity.RESULT_OK, data); 
     } 
     else { 
      getParent().setResult(Activity.RESULT_OK, data); 
     } 
    } 
    finish(); 
} 

Ecco il mio gestore onActivityResult:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == REQUEST_QUICKLIST) { 
     if (resultCode == Activity.RESULT_OK) { 
      Bundle extras = data.getExtras(); 
      if (extras != null) { 
       int id = extras.getInt("ql_id"); 
       if (id > 0) { 
        launchQLItemsThread(id); 
       } 
      } 
     } 
    } 
} 

risposta

21

Dalla documentazione di startActivityForResult: "Ad esempio, se l'attività che si sta avviando utilizza il SingleTask modalità di avvio, non verrà eseguito nel tuo compito e quindi riceverai immediatamente un risultato di annullamento. " Le attività singleInstance sono allo stesso modo.

In altre parole, se si desidera utilizzare sAFR, sarà necessario gestire più istanze di attività. Quello che vorrei consigliare è di memorizzare lo stato dell'elenco per le tue istanze ListActivity in in qualche punto globale dell'app (un singleton o qualsiasi altra cosa) e caricare da lì in onResume. Quindi, anche se verranno create più istanze ListActivity, quella superiore aggiornerà sempre i dati prima che riprendano quelli più vecchi e gli elenchi appariranno sempre aggiornati all'utente.

Nota che dovresti farlo comunque se i tuoi dati devono essere persistenti, perché l'intero processo può essere ucciso dal sistema in qualsiasi momento dopo una chiamata e se non hai salvato alcuna modifica da qualche parte il tempo che ritorna, sono suscettibili di rimanere silenziosamente persi in alcune circostanze, spesso rare e imprevedibili. In questo caso si desidera utilizzare file locali o database SQLite, non persistenti sulla rete. deve tornare rapidamente perché l'utente non può interagire con il sistema mentre è in esecuzione, quindi salvarlo nella memoria locale e quindi sincronizzarlo sulla rete in un altro momento, magari tramite un servizio lanciato da .

+0

Grazie per la risposta. Capisco cosa vuoi che faccia, tuttavia, non causerà problemi? Ovviamente dovrò fare la stessa cosa nei gestori onSaveInstanceState e onRestoreInstanceState. Se on onResume e onPause leggono e salvano le informazioni dal database, la mia applicazione leggerà inutilmente dal database e leggerà da SavedInstanceState se dovesse mai raggiungere il gestore onRestoreInstanceState, sì? Inoltre, questo è davvero ciò che è pratica comune per gli sviluppatori Android? Salvataggio dei dati di ListActivity su un singleton per più istanze di ListActivity? Ancora una volta, grazie per l'aiuto – Andrew

+0

Inoltre, potresti spiegare perché singleTop non funziona per me? O non lo capisco? – Andrew

+0

SavedInstanceState è utile solo per ripristinare lo stato di una particolare istanza di un'attività; usalo per salvare la posizione di scorrimento, ecc., non il contenuto della lista. Quello che vuoi fare è che tutte le istanze della tua attività condividano qualche stato, quindi vuoi mettere quello stato in un database se è persistente o in un membro statico se è solo una cache di dati dalla rete.Suggerisco quest'ultimo in base a ciò che hai detto; basta usare un DB per conservare i dati che devi ancora inviare in rete in futuro, in modo da non perderli. –

1

ho diversi schermi che sono ListActivities e mi piacerebbe di non andare attraverso il dolore e la sofferenza di aggiornamento degli elenchi in un precedente istanza del ListActivity quando un'altra istanza di tale ListActivity è cambiato (o c'è un modo semplice per fare lo ?).

Utilizzare un modello coerente. Ad esempio, i tuoi dati sono sperabilmente in un database. Ogni ListActivity ha un Cursor sulla parte del database di cui ha bisogno. Chiedi a Cursor di essere un "Cursore gestito" (tramite startManagingCursor()) e il tuo ListViews si aggiornerà automaticamente in onResume(). Quindi si apportano le modifiche al modello tramite il database.

Ho un menu e se vado alla mia schermata Posta in arrivo , poi vado a mio schermo QuickList , e poi vado alla mia schermata Posta in arrivo ancora una volta, crea una nuova casella di posta attività.

Questo è quello che dovrebbe fare. Citando le documentation:

Le modalità "Standard" e "singleTop" differiscono l'uno dall'altro in un solo rispetto: Ogni volta che c'è di nuovo intento per un'attività "standard", una nuova istanza della classe viene creato per rispondere a tale intento. Ogni istanza gestisce un singolo intent. Analogamente, una nuova istanza di un'attività "singleTop" può anche essere creata per gestire un nuovo intento . Tuttavia, se l'attività di destinazione ha già un'istanza esistente di l'attività nella parte superiore dello stack, , quell'istanza riceverà il nuovo intento (in una chiamata onNewIntent()); una nuova istanza non creata. In altre circostanze - per esempio, se un'istanza esistente del attività "singleTop" è nel compito bersaglio , ma non in cima alla pila, o se è in cima ad una pila, ma non nel task di destinazione: una nuova istanza verrebbe creata e inviata allo stack .

(grassetto aggiunto per enfasi)

In questo momento, il mio ListActivities, devo launchMode impostato SingleInstance.

Si prega di non farlo.

+0

Grazie per la risposta. Potresti fornirmi collegamenti ad alcune informazioni utili su cursori e database gestiti? Devo ancora implementare un database in un'applicazione Android. – Andrew

+0

Al momento (ho iniziato questa applicazione la scorsa settimana ed è la mia prima applicazione) Sto semplicemente recuperando i dati dai miei servizi web e compilando la lista. Ovviamente la creazione di una nuova istanza dell'attività avrà quindi bisogno di estrarre nuovamente i dati dal servizio web. Questo è il motivo per cui ho iniziato a usare singleInstance. Capisco la logica dietro quello che stai dicendo. Devo ancora implementare qualcosa del genere; quindi alcune risorse sarebbero utili. Grazie ancora – Andrew

Problemi correlati