Que se passe-t-il si un service Android est démarré plusieurs fois?

120

Si j'ai le code suivant:

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

Dans ce code DownloadServices'étend IntentService.

Alors maintenant, lorsque j'appelle, startService(intent)cela signifie que je démarre un nouveau service à chaque fois que je suis startService(intent)appelé ou cela signifie qu'il DownloadServiceest exécuté une fois, puis chaque fois que j'appelle, startService(intent)il passera simplement une intention différente avec un startId différent.

Cela a-t-il un sens, et lequel de ces éléments est le cas?

bytebiscuit
la source

Réponses:

167

Le service ne fonctionnera que dans une seule instance. Cependant, chaque fois que vous démarrez le service, la onStartCommand()méthode est appelée.

Ceci est documenté ici

Philipp Wendt
la source
1
Merci. Il y est également indiqué: «La méthode startService () retourne immédiatement et le système Android appelle la méthode onStartCommand () du service. Si le service n'est pas déjà en cours d'exécution, le système appelle d'abord onCreate (), puis onStartCommand ().» Donc, si le service est déjà en cours d'exécution, le système ignorera la méthode onCreate () et n'appellera que onStartCommand () ou quoi?
bytebiscuit
Je ne sais pas vraiment, mais je suis à peu près sûr que c'est le cas (fait beaucoup de sens pour ne pas appeler onCreate()si le service est déjà créé). Il devrait être facile de déterminer si vous insérez un Log.i()dans les deux rappels et vérifiez le LogCat.
Philipp Wendt
Je viens de faire ça ... et assez étrangement, il démarre le onCreate après le dernier appel startService () !!!
bytebiscuit
15
C'est parce que startService()c'est asynchrone. Ainsi, pendant que vous bouclez les appels, le service lui-même n'a pas obtenu de ressources et n'a pas encore démarré.
Philipp Wendt
1
@neelabh pas "tout de suite", il faut un certain temps pour démarrer le service, et la boucle "for" serait toujours en cours d'exécution et appelait encore et encore le service, donc les premiers essais ne trouveraient pas encore de service en cours d'exécution ... donc la méthode startService () serait appelée plusieurs fois, jusqu'à ce que le démarrage du service soit terminé. Veuillez excuser mon mauvais anglais.
mzalazar
21

Absolument correct. Une seule instance de service est créée pour un processus d'application. Et lorsque vous appelez à StartService();nouveau, alors seulement onStartCommand()est appelé et la nouvelle intention est transmise à la onStartCommand()méthode.

Remarque: onCreate() n'est pas rappelé.

À propos des appels bindService()multiples:

Lorsque vous appelez bindService()plusieurs fois, une seule instance est utilisée pour le service et Android Runtime renvoie le même objet IBinder au client.

Signifie, onBind()n'est pas appelé plusieurs fois. Et juste l'objet IBinder mis en cache est retourné.

Anish Mittal
la source
Doit onStop()-on appeler pour chaque correspondant onStartCommand?
IgorGanapolsky
6
@IgorGanapolsky: Tout d'abord, il n'y a pas de méthode de rappel onStop () dans Service. Nous devons appeler stopService () ou stopSelf () pour arrêter un service. Et quand onStartCommand () a été appelé plusieurs fois pour plusieurs intentions, alors nous devons appeler juste stopSelf () ou stopService () une seule fois. Si vous utilisez IntentService, vous devez appeler stopSelfResult (int id) en passant l'ID de démarrage de la demande depuis onHandleIntent (), ce qui arrêtera la demande d'ID de démarrage correspondante, qui a été placée dans la file d'attente de travail d'IntentService. J'espère que cela t'aides.
Anish Mittal
8

L'ajout d'informations supplémentaires aux réponses ci-dessus qui peuvent être utiles pour d'autres est startIdque la onStartCommand()méthode reçue est différente pour chaque startService()appel.

De plus, si nous écrivons dans la boucle for comme mentionné ci-dessus, le code écrit onHandleIntent()s'exécutera autant de fois que défini par la fréquence de la boucle for, mais en séquence et pas en parallèle.

Le concept est de IntentServicecréer une file d'attente de travail et chaque demande de startService()déclenchement onStartCommand()qui stocke à son tour l'intention dans la file d'attente de travail, puis transmet l'intention une par une à onHandleIntent().

Rahul Gupta
la source
2

D'après le doc :

La méthode startService () retourne immédiatement et le système Android appelle la méthode onStartCommand () du service. Si le service n'est pas déjà en cours d'exécution, le système appelle d'abord onCreate (), puis il appelle onStartCommand ().

et

Plusieurs demandes de démarrage du service entraînent plusieurs appels correspondants à onStartCommand () du service. Cependant, une seule demande d'arrêt du service (avec stopSelf () ou stopService ()) est nécessaire pour l'arrêter.

Amir Rezazadeh
la source