2010-10-10 1 views
27

Ho bisogno della mia app per Android per salvarlo su disco quando la sua attività viene messa in background o uccisa. È stato suggerito di avviare un thread quando onPause() viene chiamato ed eseguire lì costose procedure di I/O (vedere Saving/loading document state quickly and robustly for image editor).In che modo Android gestisce i thread in background quando si lascia un'attività?

In quali situazioni il sistema operativo uccide il thread e con quale frequenza si verificano queste situazioni?

Suppongo che sarà come il modo in cui vengono gestite le attività in cui il sistema operativo può decidere arbitrariamente di interrompere il thread, ma lo farà per lo più solo quando le risorse sono estremamente limitate. Sarebbe bello trovare una documentazione specifica di questo però.

Giocando in giro, con un po 'di codice di test, un thread in background avviato in onPause() verrà eseguito a tempo indeterminato in background sul mio dispositivo (ho provato a caricare un sacco di app e non sono riuscito a farlo morire).

Per la mia app specifica, sto scrivendo un editor di bitmap in cui sto utilizzando il pattern Command e il pattern Memento per consentire l'annullamento e il ripristino delle modifiche. Mi piacerebbe che l'utente fosse in grado di annullare/ripristinare le proprie modifiche anche ad es. l'utente riceve una telefonata e l'attività viene interrotta quando viene messa in background. La soluzione migliore che riesco a pensare è quella di utilizzare un thread in background per salvare costantemente il mio comando e ricordare gli oggetti sul disco durante l'uso dell'applicazione e per finire di salvare qualsiasi oggetto che rimane in un thread in background se viene chiamato onPause. Nel peggiore dei casi, se il thread viene ucciso, perderò solo alcune modifiche.

risposta

21

In quali situazioni il sistema operativo uccide il thread e con quale frequenza si verificano queste situazioni?

Il sistema operativo non uccide il thread, a meno che non stia uccidendo il processo - Android non fa nulla con i thread creati da te. Se sei il processo in primo piano, non sarai ucciso. Le probabilità che Android uccida il processo in pochi secondi dopo aver perso il primo piano (dopo lo onPause()) sono minuscole. La documentazione sulla durata del processo - cosa c'è di esso - può essere trovata here.

+1

Giusto per chiarire, se si crea un thread nel processo che è collegato ad alcune attività, questo thread verrà ucciso quando l'attività viene uccisa (cioè il processo e il thread sono collegati)? – memcom

+2

@tifftuff: un'attività non è un'applicazione. Un'attività è un componente di un'applicazione. Un'applicazione può avere molti componenti, tra cui attività multiple, servizi, ecc. Quando l'ultimo componente di un'applicazione viene distrutto (ad esempio, l'utente preme INDIETRO dall'attività one-and-only in una piccola applicazione), il processo è destinato al riciclaggio o risoluzione. NON PERDERE I FILETTI. Se avvii la discussione, devi provvedere alla sua risoluzione, poiché Android non la risolverà per te, se non terminando la procedura, che potrebbe non verificarsi per alcune settimane. – CommonsWare

+0

Grazie. Avete qualche consiglio su se un servizio sarebbe più appropriato da usare rispetto a un thread per questo lavoro in background? – memcom

1

In genere, salvare il proprio stato in è la cosa giusta da fare se è veloce. Non penso che sia chiaramente documentato quando un processo viene ucciso, ma a volte lo si vede in logcat quando si eseguono alcune applicazioni impegnative (per esempio, dopo aver eseguito Google Earth e Browser).

C'è anche un'opzione in Android DevTools per distruggere automaticamente le attività man mano che ci si allontana da esse, anche se questo probabilmente non si estende al processo. (DevTools sono sull'emulatore e su alcuni telefoni rooted).

Penso che il tuo approccio sia ragionevole - usa un thread con priorità bassa per aggiornare costantemente i dati di salvataggio, e dargli la priorità normale in onPause, e imposta un flag in onPause che dice di terminare dopo che è finito.

Ovviamente, è necessario assicurarsi che non si verifichino problemi di sincronizzazione se si arriva su Riprendi immediatamente dopo onPause (cioè mentre il thread è ancora occupato nel salvataggio).

5

La discussione può essere interrotta in qualsiasi momento dopo che l'attività è stata distrutta o non può mai essere interrotta. A seconda del tipo di thread è una pessima forma - potresti finire con un'operazione completata a metà o con un filo che rimane attaccato per sempre.

Se si desidera eseguire un'operazione in background che continua anche quando non vi è attività in primo piano, quasi sempre si desidera eseguirla all'interno di un servizio.D'altra parte, il servizio è meno probabile che venga ucciso, ma non c'è garanzia se non si utilizza "startForeground". Questo finirà per visualizzare una notifica all'utente che qualcosa sta accadendo in background, ma per quanto ne so è l'unico modo di eseguire un thread in background asincrono che è garantito che non venga ucciso.

Onestamente, la risposta corretta è assicurarsi che non ci sia mai uno stato di processo temporaneo che impiegherà molto tempo per salvare. Se si deve scrivere un file di grandi dimensioni per riflettere alcune modifiche dell'utente, considerare la possibilità di mantenere un "log delle transazioni" che è possibile utilizzare per creare un'operazione di salvataggio riavviabile. Detto questo, puoi tranquillamente eseguire i tuoi salvataggi in un servizio e sapere che anche se viene ucciso, verrà automaticamente riavviato quando le risorse saranno disponibili.

+0

La discussione terminerà entro circa 5 secondi mentre aspetto di confermare che i miei dati sono stati scritti su disco (circa 2 MB in valore). Il mio caricatore automatico terrà conto che il thread potrebbe essere eliminato prima di essere terminato e l'utente potrebbe perdere 30 secondi di lavoro. Non pensi che l'avvio di un servizio per questo è un po 'pesante? Potrei creare un log delle transazioni per le operazioni di modifica, ma anche queste devono essere salvate su disco all'uscita (dove altro posso memorizzarle rapidamente?) E l'utente potrebbe fare una modifica grande e quindi essere interrotto. – memcom

+1

L'avvio di un nuovo servizio è assolutamente * non * troppo pesante. Questo è il modo consigliato di fare le cose quando, ad esempio, si elabora una notifica Widget se ci vorrà più di un secondo. I servizi forniscono * esattamente * quello che stai cercando - il sistema si renderà conto che hanno una buona ragione per restare e tenteranno di evitare di ucciderli preventivamente, così puoi essere molto più sicuro che otterrai i tuoi 5 secondi di elaborazione in background. Sembra che tu sia già ben impostato per il raro caso in cui il servizio debba essere ucciso, quindi è tutto ciò di cui hai bisogno. – beekeeper