Entendendo a Atividade Android launchMode: standard, singleTop, singleTask e singleInstance

A tradução do artigo foi preparada especialmente para estudantes avançados no desenvolvimento do Android .




Activity é um dos conceitos mais marcantes do Android (o sistema operacional móvel mais popular com uma arquitetura de gerenciamento de memória bem projetada que implementa perfeitamente multitarefa).

De uma forma ou de outra, com o lançamento da Atividade na tela, nem tudo é tão simples. A maneira como foi executada também é importante. Existem muitas nuances neste tópico. Um dos realmente importantes é o launchMode , sobre o qual falaremos neste artigo.

Cada atividade é criada para trabalhar com objetivos diferentes. Alguns deles foram projetados para funcionar separadamente com cada Intent, por exemplo, atividade enviada para compor email no cliente de email. Enquanto outros são projetados para funcionar como um singleton, como uma caixa de correio de atividades.

É por isso que é importante indicar se você precisa criar uma nova atividade ou usar uma existente, caso contrário, isso pode levar a UX incorreto ou travar. Graças aos desenvolvedores do kernel do Android, isso é fácil de executar com o launchMode , que foi projetado especificamente para isso.

Definição de LaunchMode


Essencialmente, podemos definir o launchMode diretamente como um atributo de tag <activity>em AndroidManifest.xml:

<activity
    android:name=".SingleTaskActivity"
    android:label="singleTask launchMode"
    android:launchMode="singleTask">

Existem 4 tipos de launchMode disponíveis. Vamos olhar para eles um de cada vez.

padrão

Este é o modo padrão.

O comportamento de uma atividade definida para esse modo sempre criará uma nova atividade para trabalhar separadamente com cada intenção enviada. De fato, se 10 Intenções foram enviadas para compor um email, 10 Atividades devem ser iniciadas para atender cada Intenção separadamente. Como resultado, um número ilimitado dessas atividades pode ser iniciado no dispositivo.

Comportamento no Android pré-pirulito

Esse tipo de atividade será criado e colocado no topo da pilha na mesma tarefa que enviou a Intenção.



A imagem abaixo mostra o que acontece quando compartilhamos a imagem com a atividade padrão. Ele será empilhado na mesma tarefa descrita acima, embora seja de aplicativos diferentes.



E é isso que você verá no gerenciador de tarefas. (Pode parecer um pouco estranho)



Se mudarmos o aplicativo para outra tarefa e voltarmos para a Galeria, ainda veremos que o launchMode padrão é colocado na parte superior da tarefa da Galeria. Como resultado, se precisarmos fazer algo na Galeria, devemos primeiro terminar nosso trabalho nesta Atividade adicional.

Comportamento no Android Lollipop

Se essas atividades estiverem relacionadas ao mesmo aplicativo, o comportamento será o mesmo da implementação anterior ao Lollipop - colocando na pilha em cima da tarefa.



Porém, caso o Intent seja enviado de outro aplicativo, uma nova tarefa será criada e a Atividade recém-criada será colocada como raiz, conforme mostrado abaixo.



Isso é o que você verá no gerenciador de tarefas.



Isso ocorre porque o sistema de gerenciamento de tarefas foi modificado no Lollipop - tornou-se melhor e mais compreensível. No Lollipop, você pode simplesmente voltar para a Galeria, pois está em uma tarefa diferente. Você pode enviar outra Intenção, uma nova tarefa será criada que servirá a Intenção da mesma maneira que a anterior.



Um exemplo desse tipo de atividade é Atividade de composição de email ou Atividade de postagem de status da rede social(atualização de status nas redes sociais). Se você tem uma atividade em mente que processa cada intenção separadamente, está pensando na atividade padrão .

singleTop


O próximo modo é singleTop . Ele se comporta da mesma maneira que o padrão , o que significa que você pode criar quantas instâncias da atividade SingleTop desejar. A única diferença é que, se já existe uma instância de atividade com o mesmo tipo no topo da pilha na tarefa de chamar, nenhuma nova atividade será criado, em vez disso, a intenção será enviado para a instância Atividade existente através do método onNewIntent().



No modo singleTop, considere manipular o Intent recebido onCreate()e onNewIntent()para que ele funcione em todos os casos.

Um exemplo do uso desse modo é a função de pesquisa. Vamos pensar em criar uma caixa de pesquisa que direcione você para SearchActivity para ver os resultados da pesquisa. Para um melhor UX, geralmente sempre colocamos a caixa de pesquisa na página de resultados da pesquisa para permitir que o usuário realize a próxima pesquisa sem voltar.

Agora imagine que, se sempre lançarmos uma nova SearchActivity para exibir um novo resultado de pesquisa, obteremos 10 novas Atividades para 10 iterações da pesquisa. Seria muito estranho voltar, pois você teria que clicar 10 vezes para percorrer todos os resultados da pesquisa para retornar à atividade raiz.

Em vez disso, se o SearchActivity já estiver no topo da pilha, é melhor enviar um Intent para uma instância Activity existente e deixá-lo atualizar o resultado da pesquisa. Agora, haverá apenas uma SearchActivity localizada na parte superior da pilha, e você pode simplesmente clicar no botão Voltar uma vez para retornar à Atividade anterior. Isso faz mais sentido.

De qualquer forma, o singleTop funciona na mesma tarefa que o chamador. Se você espera que a Intenção seja enviada para uma Atividade existente, colocada em cima de qualquer outra tarefa, devo desapontá-lo ao dizer que não funciona mais. Caso o Intent seja enviado de outro aplicativo para a atividade SingleTop, a nova Atividade será iniciada no mesmo aspecto que para o launchMode padrão (pré-pirulito: colocado em cima da tarefa de chamada, pirulito: uma nova tarefa será criada) .

singleTask


Este modo é muito diferente de standart e singleTop. A atividade com singleTask launchMode pode ter apenas uma instância no sistema (ala singleton) . Se um exemplo Actividade já existe no sistema, todo a tarefa que prende a instância irá ser movida para cima, e a intenção será fornecida através do método onNewIntent(). Caso contrário, uma nova atividade será criada e colocada na tarefa correspondente.

Trabalhando em um aplicativo

Se não houvesse uma instância única do ActivityTask no sistema, uma nova será criada e simplesmente será colocada na pilha na mesma tarefa.



Mas, se existir, todas as atividades localizadas acima desta atividade de tarefa única serão automaticamente brutalmente destruídas adequadamente (o ciclo de vida é concluído) para exibir a atividade desejada no topo da pilha.Ao mesmo tempo, o Intent será enviado para a atividade SingleTask através de um método maravilhoso onNewIntent().



Não faz sentido do ponto de vista da experiência do usuário, mas foi projetado desta maneira ...

Você pode observar uma nuance mencionada na documentação :

O sistema cria uma nova tarefa e instancia uma instância de atividade na raiz da nova tarefa.

Mas, na prática, parece que isso não funciona como descrito . A atividade SingleTask ainda é colocada na parte superior da pilha de atividades da tarefa, como pode ser visto no resultado do comando dumpsys activity.

Ta

sk id #239
  TaskRecord{428efe30 #239 A=com.thecheesefactory.lab.launchmode U=0 sz=2}
  Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
    Hist #1: ActivityRecord{429a88d0 u0 com.thecheesefactory.lab.launchmode/.SingleTaskActivity t239}
      Intent { cmp=com.thecheesefactory.lab.launchmode/.SingleTaskActivity }
      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}
    Hist #0: ActivityRecord{425fec98 u0 com.thecheesefactory.lab.launchmode/.StandardActivity t239}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
      ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}

Se você deseja que o SingleTask Activity se comporte conforme descrito no documento: crie uma nova tarefa e coloque Activity como a atividade raiz. Você precisa definir um atributo taskAffinitypara a atividade SingleTask da seguinte maneira.

<activity
    android:name=".SingleTaskActivity"
    android:label="singleTask launchMode"
    android:launchMode="singleTask"
    android:taskAffinity="">

Esse será o resultado quando tentarmos executar SingleTaskActivity.





Sua tarefa é decidir se deseja usar taskAffinityou não, dependendo do comportamento desejado da Atividade.

Interagindo com outro aplicativo

Assim que o Intent for enviado de outro aplicativo e nenhuma instância de Atividade for criada no sistema, uma nova tarefa será criada com uma nova Atividade, colocada como a Atividade raiz.





Se não houver tarefa que seja o proprietário da atividade singleTask de chamada, uma nova atividade será exibida.



Se uma instância de uma atividade existir em uma tarefa, a tarefa inteira será movida para cima e, para cada atividade individual localizada acima de uma única atividade da tarefa, o ciclo de vida será concluído. Se o botão Voltar for pressionado, o usuário deverá executar a Atividade na pilha antes de retornar à tarefa de chamada.



Um exemplo do uso desse modo é qualquer Atividade do Ponto de Entrada, por exemplo, a página Caixa de Entrada de um cliente de email ou uma linha do tempo da rede social. Essas atividades não assumem mais de uma instância; portanto, a singleTask fará seu trabalho perfeitamente. De qualquer forma, você deve usar este modo com sabedoria, pois nesse modo as atividades podem ser destruídas sem a confirmação do usuário, conforme descrito acima.

instância única


Esse modo é muito semelhante ao singleTask, onde apenas uma instância de uma Atividade poderia existir em um sistema. A diferença é que uma tarefa que possui essa atividade pode ter apenas uma atividade - uma que possui um atributo singleInstance . Se outra atividade for chamada desse tipo de atividade, uma nova tarefa será criada automaticamente para acomodar essa nova atividade. Da mesma forma, se a atividade singleInstance for chamada, uma nova tarefa será criada para hospedar essa atividade.

De qualquer forma, o resultado é bastante estranho. A partir das informações fornecidasdumpsys, é claro que existem duas tarefas no sistema, mas apenas uma aparece no gerenciador de tarefas, dependendo de qual delas está no topo. Como resultado, embora exista uma tarefa que ainda esteja sendo executada em segundo plano, não podemos alterá-la novamente para o primeiro plano. Não faz nenhum sentido.

É o que acontece quando uma única atividade de instância é chamada enquanto uma atividade já existe na pilha.



E aqui está o que vemos no gerenciador de tarefas.



Como essa tarefa pode ter apenas uma atividade, não podemos mais voltar à tarefa nº 1. A única maneira de fazer isso é reiniciar o aplicativo a partir do iniciador, mas, como resultado, a tarefa singleInstance ficará oculta em segundo plano.

De qualquer forma, existem algumas soluções alternativas para esse problema. Como na atividade singleTask, basta atribuir um atributo taskAffinityà atividade singleInstance, permitindo a existência de várias tarefas no gerenciador de tarefas.

<activity
    android:name=".SingleInstanceActivity"
    android:label="singleInstance launchMode"
    android:launchMode="singleInstance"
    android:taskAffinity="">

Agora a imagem faz mais sentido.



Este modo é raramente usado. Alguns dos casos de uso práticos são um ativador de atividades ou um aplicativo para o qual você tem 100% de certeza de que deve haver apenas uma atividade. De qualquer forma, sugiro que você não use este modo, a menos que haja uma emergência.

Sinalizadores de intenção


Além AndroidManifest.xmlde definir o modo de inicialização diretamente para , também podemos ajustar o comportamento usando uma ferramenta chamada Intent flags , por exemplo:

Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

será iniciado StandardActivitycom a condição singleTop launchMode.

Existem algumas bandeiras com as quais você pode trabalhar. Você pode encontrar mais informações sobre isso aqui .

Espero que você tenha achado este artigo útil =)

Saiba mais sobre o curso

All Articles