¿Qué sucede si un servicio de Android se inicia varias veces?

120

Si tengo el siguiente código:

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

En este código se DownloadServiceextiende IntentService.

Entonces, ahora, cuando llamo, startService(intent)¿eso significa que estoy comenzando un nuevo servicio cada vez que startService(intent)se llama o eso significa que DownloadServicese ejecuta una vez y luego, cada vez que llamo startService(intent), simplemente pasará una intención diferente con un startId diferente?

¿Tiene esto sentido y cuál de estos es el caso?

bytebiscuit
fuente

Respuestas:

167

El Servicio solo se ejecutará en una instancia. Sin embargo, cada vez que inicia el servicio, onStartCommand()se llama al método.

Esto está documentado aquí

Philipp Wendt
fuente
1
Gracias. También dice: "El método startService () regresa inmediatamente y el sistema Android llama al método onStartCommand () del servicio. Si el servicio aún no se está ejecutando, el sistema primero llama a onCreate (), luego llama a onStartCommand ()". Entonces, si el servicio ya se está ejecutando, el sistema omitirá el método onCreate () y llamará solo a onStartCommand () o ¿qué?
bytebiscuit
Realmente no lo sé, pero estoy bastante seguro de que ese es el caso (tiene mucho sentido no llamar onCreate()si el servicio ya está creado). Debería ser fácil determinar si coloca una Log.i()en ambas devoluciones de llamada y verifica el LogCat.
Philipp Wendt
Acabo de hacer eso ... y, curiosamente, ¡inicia onCreate después de la última llamada startService ()!
bytebiscuit
15
Eso es porque startService()es asincrónico. Entonces, mientras está repitiendo las llamadas, el servicio en sí no ha recibido ningún recurso y aún no ha comenzado.
Philipp Wendt
1
@neelabh no "de inmediato", se necesita algo de tiempo para iniciar el servicio, y el ciclo "for" seguiría ejecutándose y llamando una y otra vez al servicio, por lo que los primeros intentos no encontrarían ningún servicio en ejecución todavía ... por lo que el método startService () se llamaría un par de veces, hasta que se complete el inicio del servicio. Disculpe mi mal inglés.
mzalazar
21

Absolutamente correcto. Solo se crea una instancia de Servicio para un proceso de solicitud. Y cuando vuelves a llamar StartService();, solo onStartCommand()se llama y se pasa un nuevo Intent al onStartCommand()método.

Nota: onCreate() no se vuelve a llamar.

Acerca de llamar bindService()varias veces:

Cuando llamas bindService()varias veces, solo se usa una instancia para el servicio y Android Runtime devuelve el mismo objeto IBinder al cliente.

Significa, onBind()no se llama varias veces. Y se devuelve el objeto IBinder en caché.

Anish Mittal
fuente
¿ onStop()Tiene que ser llamado para cada correspondencia onStartCommand?
IgorGanapolsky
6
@IgorGanapolsky: Primero que nada, no existe tal método de devolución de llamada onStop () en Service. Necesitamos llamar a stopService () o stopSelf () para detener un servicio. Y cuando se ha llamado a onStartCommand () varias veces para múltiples intenciones, entonces necesitamos llamar solo a stopSelf () o stopService () solo una vez. Si usa IntentService, debe llamar a stopSelfResult (int id) pasando el ID de inicio de la solicitud de onHandleIntent (), que detendrá la solicitud de ID de inicio correspondiente, que se colocó en la cola de trabajo de IntentService. Espero que esto ayude.
Anish Mittal
8

Agregar más información a las respuestas anteriores que puede ser útil para otros es startIdque el onStartCommand()método que recibe es diferente para cada startService()llamada.

Además, si escribimos el bucle for como se mencionó anteriormente, el código escrito onHandleIntent()se ejecutaría tantas veces como lo define la frecuencia del bucle for, pero en secuencia y no en paralelo.

El concepto es IntentServicecrear una cola de trabajo y cada solicitud de startService()activación, onStartCommand()que a su vez almacena la intención en la cola de trabajo y luego pasa la intención una por una onHandleIntent().

Rahul Gupta
fuente
2

Según el doc :

El método startService () regresa inmediatamente y el sistema Android llama al método onStartCommand () del servicio. Si el servicio aún no se está ejecutando, el sistema primero llama a onCreate () y luego llama a onStartCommand ().

y

Varias solicitudes para iniciar el servicio dan como resultado múltiples llamadas correspondientes al onStartCommand () del servicio. Sin embargo, solo se requiere una solicitud para detener el servicio (con stopSelf () o stopService ()) para detenerlo.

Amir Rezazadeh
fuente