A forma como o Android gerencia as tarefas e o back stack - colocando as atividades em uma sucessão na mesma tarefa e usando o conceito last in, first out - funciona perfeitamente para a maioria das aplicações e você não deveria se preocupar sobre como as atividades são associadas às tarefas ou como elas existem no back stack. Contudo, você deve decidir se quer interromper o comportamento padrão. Talvez você queira que uma atividade em sua aplicação comece uma nova tarefa quando ela é iniciada (ao invés de ser colocada como a tarefa corrente); ou, quando você inicia uma atividade, você queira trazer para a frente uma instância existente dela (ao invés de criar uma nova instância no topo do back stack); ou talvez você queira que seu back stack sera limpo de todas as atividades e só tenha uma atividade (a atividade root) quando o usuário saia da tarefa.
Você pode fazer isso e muitas outras coisas usando o atributo <activity> que se encontra no manifesto do Android e com flags em seus intents que você passa para o startActivity().
Nesse sentido, os atributos principals de <activity> que você pode usar são:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainsTaskState
finishOnTaskLaunch
E as flags de intent que você pode usar são:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
Definindo os modos de lançamento (launch modes)
Launch modes permitem a você definir ua nova instância de uma atividade que está associada à tarefa corrente. Você pode definir diferentes launch modes de duas maneiras:
Usando o arquivo de manifesto
Quando você declara uma atividade em seu arquivo de manifesto, você pode manifestar como a atividade deverá ser associada com tarefa quando ela se inicia
Usando intent flags
Quando você chama startActivity(), você pode incluir a flag dentro do Intent que declara como (ou se) uma nova atividade deverá ser associada com a tarefa corrente.
Ou seja, se a atividade A inicia a atividade B, a atividade B pode definir em seu manifesto como ela deverá ser associada com a tarefa corrente e a atividade A pode também requisitar como a atividade B deve ser associada com a tarefa corrente. Se ambas atividades definem como a atividade B deveria ser associada com a tarefa, então a requisição da atividade A (como definida em seu intent) é honrada sobre a requisição da atividade B.
Usando o arquivo de manifesto
Quando se declara uma atividade no arquivo de manifesto, você pode especificar como a atividade estará associada com a tarefa usando o elemento <activity> dentro do atributo launchMode.
O atributo launchMode especifica uma instrução sobre como a atividade deve ser lançada dentro da tarefa. Existem quatro tipos diferentes de launch modes que você pode assinalar no atributo launchMode:
"standard" (o modo padrão)
O sistema cria uma nova instância da atividade na tarefa a partir da tarefa já existente e faz a rota do intent para ele. A atividade pode ser instanciada multiplas vezes e cada instância pode pertencer a diferentes tarefas e uma tarefa pode ter multiplas intâncias.
"singleTop"
Se uma instância de uma atividade já existe no topo da atividade corrente, o sistema faz o roteamento do intent para a instância através de uma chamada para o método onNewIntent(), ao invés de criar uma nova instância da atividade. A atividade pode ser instanciada multiplas vezes e cada instância pode pertencer a tarefas diferentes e uma tarefa pode ter multiplas instâncias (mas apenas se a atividade que estiver no topo do back stack não for uma instância existente da atividade).
Por exemplo, suponha que o back stack de uma tarefa consista da atividade raiz de A com as atividades B, C e D no topo (o stack ficaria como A-B-C-D onde D está no topo). Um intent chega para a atividade do tipo D. Se D tem o modo de launch mode em standard, uma nova instância da classe é lançada e o back stack se torna A-B-C-D-D. Contudo, se a atividade D estiver em modo singleTop, a instância existente de D é entregue ao intent através de onNewIntent(), já que está no topo do back stack - o back stack continua como A-B-C-D. Mas, se um intent chega para a atividade do tipo B, então uma nova instância de B é adicionada ao back stack, mesmo que o launch mode esteja em singleTop, fazendo com que o back stack fique como A-B-C-D-B.
"singleTask"
O sistema cria uma nova tarefa e instancia a atividade na raiz da nova tarefa. Contudo, se uma instância da atividade já existe em uma tarefa separada, o sistema faz o roteamento do intent para a instância existente através de uma chamada para o método onNewIntent(), ao invés de criar uma nova instância. Apenas uma instância de cada atividade pode existir a cada vez.
"singleInstance"
O mesmo que singleTask, exceto que o sistema não lança nenhuma outra atividade dentro da tarefa que está relacionada à instância. A atividade é simple única e o único membro de sua tarefa; quaisquer outras atividades iniciadas são apenas em uma tarefa separada.
Como outro exemplo, a aplicação de navegador do Android declara que a atividade de navegação deve sempre abrir sua própria tarefa - ela especifica que é singleTask no lanch mode em seu elemento <activity>. Isso significa que se sua aplicação tem um intent para abrir o navegador, a atividade não é colocada na mesma tarefa de sua aplicação. Ao invés disso, ele inicia uma tarefa nova apenas para o navegador ou, se o navegador já está aberto, a tarefa é chamada para a tela para receber a requisição.
Independente da atividade iniciar uma nova tarefa ou não ou a mesma tarefa como atividade ser aberta, o BACK sempre volta para a atividade anterior. Apesar disso ser verdade, se você iniciar uma atividade a partir de sua tarefa (Task A) que especifica o launch mode como singleTask, então a sua atividade deve ter uma instância no background que pertença a tarefa com seu próprio back stack (Task B). Nesse caso, quando a Task B for lançada para a tela para receber o novo intent, o BACK navega por todas as atividades da Task B antes de retornar para a atividade que está no topo da Task A. A imagem abaixo ilustra esse cenário.
Não existe nenhum atributo de launchMode que produza esse comportamento.
Essa flag é mais comumente usada em conjunção com FLAG_ACTIVITY_NEW_TASK. Quando usadas em conjunto, essas flags são uma forma de localizar uma atividade existente em outra tarefa e colocá-la em uma posição onde possa responder a um intent.
Gerenciando afinidades
Uma affinity (afinidade) indica para qual tarefa uma atividade prefere pertencer. Por padrão, todas as atividades de uma mesma aplicação tem afinidade umas às outras. Então, por padrão, todas as atividades de uma aplicação preferem estar dentro da mesma tarefa. Mas, você pode modificar a afinidade padrão de uma atividade. Atividades definidas em aplicações diferentes podem compartilhar uma afinidade, ou atividades definidas na mesma aplicação podem ser marcadas para ter afinidades distintas.
Você pode modificar a atividade de qualquer dada atividade com o atributo taskAffinity dentro do elemento <activity>.
O atributo taskAffinity recebe um valor string que deve ser único do nome de pacote padrão declarado no elemento <manifest>, pois o sistema usa o nome para identificar a tarefa padrão de afinidade da aplicação.
A afinidade deve ser usada em duas circunstâncias:
- Quando um intent que lança uma atividade contém a flag FLAG_ACTIVITY_NEW_TASK.
Uma nova atividade é, por padrão, lançada dentro da tarefa da atividade que chamou o startActivity(). Ela é colocada no mesmo back stack de quem fez a sua chamada. Mas, se o intent passado para o startActivity() contém a flag FLAG_ACTIVITY_NEW_TASK, o sistema procura por uma tarefa diferente para hospedar a nova atividade. Em muitos casos, é uma nova tarefa a ser criada. Só que não precisa ser assim. Se já existe uma tarefa com a mesma afinidade da nova atividade, a atividade é lançada nessa tarefa. Se não existe, então é criada uma nova tarefa.
Se essa flag fizer com que a atividade seja criada numa nova tarefa e o usuário pressionar o botão HOME, então deve haver alguma maneira do usuário navegar de volta à tarefa. Algumas entidades (como o gerenciador de notificação) sempre inicia atividades em uma tarefa externa, nunca como parte de sua própria tarefa e, por conta disso, eles sempre colocar a flag de nova tarefa em seus intents quando eles chamam startActivity(). Se você tem uma atividade que pode ser chamada por uma entidade externa que use essa flag, tome cuidado para que o usuário tenha uma maneira de voltar para a tarefa que foi iniciada.
- Quando uma atividade tem o atributo allowTaskReparenting setado para true.
Nesse caso, a atividade pode mover-se da tarefa que ela iniciou para uma tarefa que tenha afinidade quando a tarefa vai para a tela.
Por exemplo, suponha que uma atividade que reporte as condições de tempo em cidades selecionadas sejam definidas como parte de uma aplicação de viagens. Ela tem a mesma afinidade de outras atividades na mesma aplicação e permite o re-parenting em seus atributos. Quando uma das atividades inicia a atividade de tempo, ele inicialmente pertence à mesma tarefa de sua atividade. Contudo, quando a tarefa da aplicação de viagens vem para a frente, a atividade de tempo é reassinalada (re-parented) para essa tarefa e mostrada dentro dela.
Se esse atributo está setado como true na raiz da tarefa, o comportamento padrão mencionado acima não acontece. A tarefa mantém todas as atividades no stack mesmo após um longo período.
<activity ... >
<intent-filter ... >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
...
</activity>
0 comentários:
Postar um comentário