Co się stanie, jeśli usługa Android jest uruchamiana wiele razy?

120

Jeśli mam następujący kod:

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

W tym kodzie DownloadServicerozszerza IntentService.

Więc teraz, kiedy dzwonię startService(intent), oznacza to, że uruchamiam nową usługę za każdym razem, gdy startService(intent)jest wywoływana, lub oznacza to, że DownloadServicejest uruchamiana raz, a następnie za każdym razem, gdy dzwonię startService(intent), po prostu przejdzie inną intencję z innym startId.

Czy to ma sens i który z nich ma miejsce?

bytebiscuit
źródło

Odpowiedzi:

167

Usługa będzie działać tylko w jednym wystąpieniu. Jednak za każdym razem, gdy uruchamiasz usługę, onStartCommand()wywoływana jest metoda.

Jest to udokumentowane tutaj

Philipp Wendt
źródło
1
Dzięki. Jest tam również napisane: „Metoda startService () zwraca natychmiastowo, a system Android wywołuje metodę onStartCommand () usługi. Jeśli usługa nie jest jeszcze uruchomiona, system najpierw wywołuje onCreate (), a następnie wywołuje onStartCommand ().” Więc jeśli usługa już działa, to system pominie metodę onCreate () i wywoła tylko onStartCommand (), czy co?
bytebiscuit
Naprawdę nie wiem, ale jestem prawie pewien, że tak jest (dlatego warto nie dzwonić, onCreate()jeśli usługa jest już utworzona). Powinno być łatwe do ustalenia, czy umieścisz a Log.i()w obu wywołaniach zwrotnych i sprawdzisz LogCat.
Philipp Wendt,
Właśnie to zrobiłem ... i, o dziwo, uruchamia onCreate po ostatnim wywołaniu startService () !!!
bytebiscuit
15
Dzieje się tak, ponieważ startService()jest asynchroniczny. Więc gdy zapętlasz połączenia, sama usługa nie uzyskała żadnych zasobów i jeszcze się nie uruchomiła.
Philipp Wendt
1
@neelabh nie „od razu”, uruchomienie usługi zajmuje trochę czasu, a pętla „for” nadal działałaby i wywoływałaby usługę raz po raz, więc pierwsze próby nie znalazłyby jeszcze uruchomionej usługi ... więc metoda startService () byłaby wywoływana kilka razy, aż do zakończenia uruchamiania usługi. Proszę wybaczyć mój zły angielski.
mzalazar
21

Absolutnie poprawne. Dla procesu aplikacji tworzona jest tylko jedna instancja usługi. A kiedy zadzwonisz StartService();ponownie, onStartCommand()zostanie wywołany i nowy Intent jest przekazywany do onStartCommand()metody.

Uwaga: onCreate() nie jest ponownie wywoływany.

Informacje o bindService()wielokrotnym dzwonieniu :

Gdy wywołujesz bindService()wiele razy, ponownie tylko jedno wystąpienie jest używane dla usługi, a środowisko wykonawcze systemu Android zwraca ten sam obiekt IBinder do klienta.

Znaczy, onBind()nie jest wywoływany wielokrotnie. Zwracany jest tylko obiekt IBinder z pamięci podręcznej.

Anish Mittal
źródło
Czy onStop()trzeba wywołać każdą korespondencję onStartCommand?
Igor Ganapolsky
6
@IgorGanapolsky: Przede wszystkim nie ma takiej metody wywołania zwrotnego onStop () w usłudze. Aby zatrzymać usługę, musimy wywołać stopService () lub stopSelf (). A gdy metoda onStartCommand () została wywołana wiele razy w wielu celach, wystarczy wywołać stopSelf () lub stopService () tylko raz. Jeśli używasz IntentService, powinieneś wywołać stopSelfResult (int id) przekazując start id żądania z onHandleIntent (), co zatrzyma odpowiednie żądanie startowe, które zostało umieszczone w kolejce roboczej IntentService. Mam nadzieję że to pomoże.
Anish Mittal
8

Dodanie dodatkowych informacji do powyższych odpowiedzi, które mogą być pomocne dla innych, polega na tym, startIdże onStartCommand()metoda odbiera jest inna dla każdego startService()połączenia.

Również, jeśli napiszemy pętlę for, jak wspomniano powyżej, kod napisany w programie onHandleIntent()będzie wykonywał się tyle razy, ile jest zdefiniowane przez częstotliwość pętli for, ale sekwencyjnie, a nie równolegle.

Koncepcja polega na IntentServiceutworzeniu kolejki roboczej i każdym żądaniu startService()wyzwalania, onStartCommand()które z kolei przechowuje intencję w kolejce roboczej, a następnie przekazuje intencję jeden po drugim onHandleIntent().

Rahul Gupta
źródło
2

Według doc :

Metoda startService () zwraca natychmiastowo, a system Android wywołuje metodę onStartCommand () usługi. Jeśli usługa nie jest jeszcze uruchomiona, system najpierw wywołuje onCreate (), a następnie wywołuje onStartCommand ().

i

Wiele żądań uruchomienia usługi powoduje wiele odpowiednich wywołań funkcji onStartCommand () usługi. Jednak tylko jedno żądanie zatrzymania usługi (stopSelf () lub stopService ()) jest wymagane, aby ją zatrzymać.

Amir Rezazadeh
źródło