O que acontece se um serviço Android for iniciado várias vezes?

120

Se eu tiver o seguinte código:

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

Neste código DownloadServiceestende IntentService.

Então, agora, quando estou chamando startService(intent), isso significa que estou iniciando um novo serviço toda vez que startService(intent)é chamado ou significa que DownloadServiceé executado uma vez e, a cada vez que o chamo startService(intent), passará um intent diferente com um startId diferente.

Isso faz sentido, e qual é o caso?

bytebiscuit
fonte

Respostas:

167

O serviço será executado apenas em uma instância. No entanto, toda vez que você inicia o serviço, o onStartCommand()método é chamado.

Isso está documentado aqui

Philipp Wendt
fonte
1
Obrigado. Ele também diz: "O método startService () retorna imediatamente e o sistema Android chama o método onStartCommand () do serviço. Se o serviço ainda não estiver em execução, o sistema primeiro chama onCreate () e, em seguida, chama onStartCommand ()." Portanto, se o serviço já estiver em execução, o sistema pulará o método onCreate () e chamará apenas onStartCommand () ou o quê?
bytebiscuit
Na verdade não sei, mas tenho quase certeza que é o caso (faz muito sentido não ligar onCreate()se o serviço já estiver criado). Deve ser fácil determinar se você colocou um Log.i()em ambos os callbacks e verificou o LogCat.
Philipp Wendt
Simplesmente fiz isso ... e estranhamente ele inicia o onCreate após a última chamada startService () !!!
bytebiscuit
15
Isso porque startService()é assíncrono. Portanto, enquanto você está fazendo o loop das chamadas, o serviço em si não obteve nenhum recurso e ainda não foi iniciado.
Philipp Wendt
1
@neelabh não "imediatamente", leva algum tempo para iniciar o serviço, e o loop "for" ainda estaria em execução e chamando o serviço novamente e novamente, então as primeiras tentativas não encontrariam nenhum serviço em execução ainda ... portanto, o método startService () seria chamado algumas vezes, até que a inicialização do serviço fosse concluída. Por favor, desculpe meu inglês ruim.
mzalazar,
21

Absolutamente correto. Apenas uma instância de serviço é criada para um processo de aplicativo. E quando você chama StartService();novamente, então apenas onStartCommand()é chamado e um novo Intent é passado para o onStartCommand()método.

Nota: onCreate() não é chamado novamente.

Sobre ligar bindService()várias vezes:

Quando você chama bindService()várias vezes, novamente apenas uma instância é usada para o serviço e o Android Runtime retorna o mesmo objeto IBinder para o cliente.

Significa, onBind()não é chamado várias vezes. E apenas o objeto IBinder em cache é retornado.

Anish Mittal
fonte
Tem onStop()que ser chamado para cada correspondente onStartCommand?
IgorGanapolsky 01 de
6
@IgorGanapolsky: Em primeiro lugar, não existe esse método de retorno de chamada onStop () em Service. Precisamos chamar stopService () ou stopSelf () para interromper um serviço. E quando onStartCommand () foi chamado várias vezes para vários intents, precisamos chamar apenas stopSelf () ou stopService () apenas uma vez. Se estiver usando IntentService, você deve chamar stopSelfResult (int id) passando a id de início da solicitação de onHandleIntent (), que interromperá a solicitação de id de início correspondente, que foi colocada na fila de trabalho de IntentService. Espero que isto ajude.
Anish Mittal
8

Adicionando mais algumas informações às respostas acima, o que pode ser útil para outras pessoas, é startIdque o onStartCommand()método recebido é diferente para cada startService()chamada.

Além disso, se escrevermos no loop for conforme mencionado acima, o código escrito onHandleIntent()seria executado tantas vezes conforme definido pela frequência do loop for, mas em sequência e não em paralelo.

O conceito é IntentServicecriar uma fila de trabalho e cada solicitação de startService()acionamento onStartCommand()que, por sua vez, armazena o intent na fila de trabalho e, em seguida, passa o intent um por um para onHandleIntent().

Rahul Gupta
fonte
2

De acordo com o doc :

O método startService () retorna imediatamente e o sistema Android chama o método onStartCommand () do serviço. Se o serviço ainda não estiver em execução, o sistema primeiro chama onCreate () e, em seguida, chama onStartCommand ().

e

Várias solicitações para iniciar o serviço resultam em várias chamadas correspondentes para onStartCommand () do serviço. No entanto, apenas uma solicitação para interromper o serviço (com stopSelf () ou stopService ()) é necessária para interrompê-lo.

Amir Rezazadeh
fonte