Cosa succede se un servizio Android viene avviato più volte?


120

Se ho il seguente codice:

Intent intent = new Intent(this,DownloadService.class);     
for(int i=0;i<filesArray.length;i++){        
     startService(intent);          
}

In questo codice si DownloadServiceestende IntentService.

Quindi ora quando chiamo startService(intent)significa che sto avviando un nuovo servizio ogni volta che startService(intent)viene chiamato o significa che DownloadServiceviene eseguito una volta e quindi ogni volta che lo chiamo startService(intent)passerà solo un intento diverso con un ID iniziale diverso.

Ha senso, e quale di questi è il caso?

Risposte:


167

Il servizio verrà eseguito solo in un'istanza. Tuttavia, ogni volta che si avvia il servizio, onStartCommand()viene chiamato il metodo.

Questo è documentato qui


1
Grazie. Dice anche lì: "Il metodo startService () ritorna immediatamente e il sistema Android chiama il metodo onStartCommand () del servizio. Se il servizio non è già in esecuzione, il sistema prima chiama onCreate (), quindi chiama onStartCommand ()." Quindi, se il servizio è già in esecuzione, il sistema salterà il metodo onCreate () e chiamerà solo onStartCommand () o cosa?
bytebiscuit

Non lo so davvero, ma sono abbastanza sicuro che sia così (fa molto senso non chiamare onCreate()se il servizio è già stato creato). Dovrebbe essere facile determinare se si inseriscono Log.i()entrambi i callback e si controlla il LogCat.
Philipp Wendt

L'ho appena fatto ... e stranamente avvia onCreate dopo l'ultima chiamata a startService () !!!
bytebiscuit

15
Questo perché startService()è asincrono. Quindi, mentre stai ripetendo le chiamate, il servizio stesso non ha ottenuto alcuna risorsa e non è ancora stato avviato.
Philipp Wendt

1
@neelabh non "subito", ci vuole un po 'di tempo per avviare il servizio e il ciclo "for" sarebbe ancora in esecuzione e chiamerebbe ancora e ancora il servizio, quindi i primi tentativi non troverebbero ancora alcun servizio in esecuzione ... quindi il metodo startService () verrebbe chiamato un paio di volte, fino al completamento dell'avvio del servizio. Per favore scusa il mio cattivo inglese.
mzalazar

21

Assolutamente corretto. Viene creata solo un'istanza di servizio per un processo di applicazione. E quando si chiama di StartService();nuovo, onStartCommand()viene solo chiamato e il nuovo Intent viene passato al onStartCommand()metodo.

Nota: onCreate() non viene richiamato.

Informazioni sulle chiamate bindService()multiple:

Quando si chiama bindService()più volte, viene utilizzata di nuovo solo un'istanza per il servizio e Android Runtime restituisce lo stesso oggetto IBinder al client.

Significa, onBind()non viene chiamato più volte. E viene restituito solo l'oggetto IBinder memorizzato nella cache.


Deve onStop()essere chiamato per ogni corrispondente onStartCommand?
IgorGanapolsky

6
@IgorGanapolsky: Prima di tutto, non esiste un tale metodo di callback onStop () nel servizio. Dobbiamo chiamare stopService () o stopSelf () per interrompere un servizio. E quando onStartCommand () è stato chiamato più volte per più intenti, è necessario chiamare solo stopSelf () o stopService () solo una volta. Se si utilizza IntentService, è necessario chiamare stopSelfResult (int id) passando l'ID iniziale della richiesta da onHandleIntent (), che interromperà la richiesta dell'ID iniziale corrispondente, che è stata inserita nella coda di lavoro di IntentService. Spero che questo ti aiuti.
Anish Mittal

8

Aggiungendo qualche informazione in più alle risposte di cui sopra che possono essere utili per gli altri, startIdil onStartCommand()metodo che riceve è diverso per ogni startService()chiamata.

Inoltre, se scriviamo un ciclo for come menzionato sopra, il codice scritto in onHandleIntent()verrà eseguito tante volte come definito dalla frequenza del ciclo for, ma in sequenza e non in parallelo.

Il concetto è IntentServicecreare una coda di lavoro e ogni richiesta di startService()trigger onStartCommand()che a sua volta memorizza l'intento nella coda di lavoro e quindi passa l'intento uno per uno a onHandleIntent().


2

Secondo il doc :

Il metodo startService () restituisce immediatamente e il sistema Android chiama il metodo onStartCommand () del servizio. Se il servizio non è già in esecuzione, il sistema chiama prima onCreate (), quindi chiama onStartCommand ().

e

Più richieste per avviare il servizio risultano in più chiamate corrispondenti a onStartCommand () del servizio. Tuttavia, è necessaria solo una richiesta per arrestare il servizio (con stopSelf () o stopService ()) per arrestarlo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.