Uma tarefa é uma coleção de atividades com as quais os usuários interagem ao tentar fazer algo no seu app. Essas atividades são organizadas em uma pilha chamada backstack na ordem em que cada atividade é aberta.
Por exemplo, um app de e-mails pode ter uma atividade para mostrar uma lista de novas mensagens. Quando o usuário seleciona uma nova atividade será aberta para exibir essa mensagem. Esta nova atividade foi adicionada para a backstack. Então, quando o usuário toca ou faz um gesto para "Voltar", essa nova atividade termina e é retirado da pilha.
Ciclo de vida de uma tarefa e da backstack dela
A tela inicial do dispositivo é o local de início da maioria das tarefas. Quando um usuário toca o ícone de um app ou atalho no Acesso rápido aos apps ou na tela inicial; a tarefa desse app fica em primeiro plano. Se não houver nenhuma tarefa para o aplicativo, então uma uma nova tarefa é criada e o main atividade desse app é aberto como a atividade raiz na pilha.
Quando a atividade atual iniciar outra, a nova atividade será colocada na parte superior da pilha e recebe foco. A atividade anterior permanece na pilha, mas parou. Quando uma atividade é interrompida, o sistema mantém o estado atual da de uma ferramenta de visualização. Quando o usuário realiza a ação de voltar, a atividade atual é do topo da pilha e destruída. A a atividade anterior é retomada e o estado anterior da interface é restaurado.
Atividades no nunca são reorganizadas, apenas são colocadas e retiradas da pilha conforme são iniciado pela atividade atual e dispensado pelo usuário. pelo botão ou gesto "Voltar". Portanto, a backstack opera uma estrutura de objeto último a chegar, primeiro a sair. A Figura 1 mostra uma linha do tempo com atividades sendo enviadas e retiradas de uma backstack.
À medida que o usuário continua tocando ou fazendo gesto de voltar, cada atividade na pilha é retirado para revelar o anterior, até que o usuário retorne à tela inicial tela ou qualquer atividade que estava em execução quando a tarefa começou. Quando todos atividades forem removidas da pilha, a tarefa não existirá mais.
Comportamento de tocar na tela "Voltar" para atividades raiz da tela de início
As atividades raiz da tela de início são atividades que declaram uma intent
filtrar por ambas
ACTION_MAIN
e
CATEGORY_LAUNCHER
Essas atividades são únicas porque atuam como pontos de entrada para o aplicativo a partir de
Acesso rápido aos apps e são usados para iniciar uma tarefa.
Quando um usuário toca ou faz um gesto para "Voltar" de uma atividade raiz da tela de início, o sistema processa o evento de forma diferente, dependendo da versão do Android que dispositivo está sendo executado.
- Comportamento do sistema no Android 11 e versões anteriores
- O sistema encerra a atividade.
- Comportamento do sistema no Android 12 e versões mais recentes
O sistema move a atividade e a tarefa para o segundo plano, em vez de para finalizar a atividade. Esse comportamento corresponde ao comportamento padrão do sistema quando sair de um app usando o botão home ou o gesto.
Na maioria dos casos, esse comportamento significa que os usuários podem retomar o app mais rapidamente de um estado quente, em vez de ter que reiniciar completamente o app de uma rede a frio atual.
Se você precisar fornecer uma navegação de retorno personalizada, recomendamos o uso das APIs de atividade do AndroidX em vez de
onBackPressed()
As APIs Activity do AndroidX adotam automaticamente comportamento apropriado do sistema se não houver componentes interceptando o sistema Tocar na parte de trás.No entanto, se o app modificar
onBackPressed()
para processar Navegue de volta e conclua a atividade, atualize sua implementação para chamar atésuper.onBackPressed()
em vez de finalizar. Ligando Osuper.onBackPressed()
move a atividade e a tarefa dela para o segundo plano quando apropriado e oferece uma experiência de navegação mais consistente para os usuários entre apps.
Tarefas em segundo e primeiro plano
Uma tarefa é uma unidade coesa que pode ser movida para segundo plano quando um usuário inicia uma uma nova tarefa ou vai para a tela inicial. Em segundo plano, todas as atividades na tarefa são interrompidas, mas a backstack da tarefa permanece intacta (a tarefa perde o foco enquanto outra tarefa ocorre, como mostrado na figura 2. Um a tarefa pode retornar ao primeiro plano para que os usuários possam continuar de onde pararam
Considere o seguinte fluxo de tarefas para a Tarefa A atual que tem três atividades na pilha, incluindo duas na atividade atual:
O usuário usa o botão ou o gesto "Página inicial" e inicia um novo app no Acesso rápido aos apps.
Quando a tela inicial aparece, a Tarefa A fica em segundo plano. Quando o novo é iniciado, o sistema inicia uma tarefa para esse app (Tarefa B) com sua própria pilha das atividades.
Depois de interagir com o aplicativo, o usuário retorna à Página inicial novamente e seleciona o aplicativo que iniciou originalmente a Tarefa A.
Agora, a Tarefa A fica em primeiro plano. Todas as três atividades da pilha estão intactas e a atividade no topo da pilha é retomada. Neste ponto, o usuário também pode voltar para a Tarefa B acessando a tela inicial e selecionando o ícone do app que iniciou essa tarefa ou selecionando a tarefa do app no menu Recentes tela.
Várias instâncias de atividade
Como as atividades na backstack nunca são reorganizadas, se o seu app permite que os usuários iniciem uma atividade específica a partir de mais de uma atividade, uma nova instância dessa atividade é criada e enviada para a pilha, em vez de trazendo qualquer instância anterior da atividade para o topo. Dessa forma, um no seu app pode ser instanciada várias vezes, mesmo de diferentes tarefas, como mostrado na Figura 3.
Se o usuário navegar para trás usando o botão "Voltar" botão ou gesto, as instâncias da atividade são reveladas na ordem em que estão abertos, cada um com o próprio estado da interface. No entanto, é possível modificar essa do comportamento se não quiser que uma atividade seja instanciada mais de uma vez. Aprender mais sobre isso na seção sobre gerenciamento tarefas.
Ambientes de várias janelas
Quando apps são executados simultaneamente em um com várias janelas ambiente, com suporte no Android 7.0 (API nível 24) e superiores, o sistema gerencia as tarefas separadamente para cada janela. Cada pode ter várias tarefas. O mesmo se aplica a apps para Android executados em Chromebooks: o sistema gerencia tarefas, ou grupos de tarefas, em uma por janela.
Resumo do ciclo de vida
Para resumir o comportamento padrão das atividades e tarefas:
Quando a atividade A inicia a atividade B, a atividade A é interrompida, mas o sistema mantém seu estado, como a posição de rolagem e o texto inserido nos formulários. Se o usuário toca ou usa o gesto "Voltar" na atividade B, na atividade A será retomado com o estado restaurado.
Quando o usuário sai de uma tarefa usando o botão home ou o gesto, o servidor atividade é interrompida e sua tarefa fica em segundo plano. O sistema mantém o estado de cada atividade na tarefa. Se o usuário retomar a tarefa mais tarde selecionando o ícone na tela de início que iniciava a tarefa, a tarefa chega ao primeiro plano e retoma a atividade no topo da pilha.
Se o usuário tocar ou fizer um gesto para "Voltar", a atividade atual será retirada do da pilha e destruídos. A atividade anterior na pilha será retomada. Quando uma atividade é destruída, o sistema não retém o estado da atividade.
Esse comportamento é diferente para atividades raiz da tela de início quando o app está sendo executado em um dispositivo com o Android 12 ou mais recente.
As atividades podem ser instanciadas várias vezes, até mesmo em outras tarefas.
Gerenciar tarefas
O Android gerencia tarefas e a backstack colocando todas as atividades começaram em sequência na mesma tarefa, em último em, primeiro a pilha de saída. Isso funciona muito bem para a maioria dos apps, e você geralmente não precisa se preocupar como suas atividades estão associadas a tarefas ou como elas existem nos bastidores pilha.
No entanto, você pode decidir que deseja interromper o comportamento normal. Por exemplo, você pode querer que uma atividade no aplicativo comece uma nova tarefa quando estiver começou, em vez de serem colocados na tarefa atual. Ou, quando você inicia um atividade, você pode querer trazer adiante uma instância existente dela, em vez de criar uma nova instância na parte de cima da backstack. Ou você pode você quer que todas as atividades da backstack sejam removidas, exceto a raiz quando o usuário sair da tarefa.
Você pode fazer isso e muito mais usando atributos na
Elemento do manifesto <activity>
e flags na intent que você transmite ao
startActivity()
Estes são os principais atributos de <activity>
que podem ser usados para gerenciar tarefas:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
Estas são as principais flags de intent que você pode usar:
As seções a seguir discutem como usar esses atributos de manifesto e sinalizações de intent para definir como as atividades se associam às tarefas e como elas se comportam na backstack.
Também são discutidas as considerações sobre como as tarefas e atividades são representados e gerenciados na tela "Recentes". Normalmente, você permite que o definem como as tarefas e atividades são representadas no recentes. Você não precisará modificar esse comportamento. Para mais mais informações, consulte Tela Recentes.
Definir modos de inicialização
Os modos de inicialização permitem definir como uma nova instância de uma atividade é associada com a tarefa atual. É possível definir os modos de inicialização de duas maneiras, descritas nas seções a seguir:
Como usar o arquivo de manifesto
Ao declarar uma atividade no arquivo de manifesto, é possível especificar como o se associa a tarefas quando é iniciada.
Como usar sinalizações de intent
Quando você ligar
startActivity()
, é possível incluir um sinalizadorIntent
que declara como (ou se) a nova atividade se associa à tarefa atual.
Portanto, se a atividade A iniciar a atividade B, ela poderá ser definida no manifesto. como ele se associa à tarefa atual, e a atividade A pode usar uma flag de intent para solicitar como a atividade B pode se associar à tarefa atual.
Se os dois as atividades definem como a atividade B se associa a uma tarefa, e a atividade A solicitação, conforme definido na intent, é honrada em relação à solicitação da Atividade B, conforme definido no manifesto.
Definir modos de inicialização usando o arquivo de manifesto
Ao declarar uma atividade no arquivo de manifesto, é possível especificar como o
se associa a uma tarefa usando o
<activity>
do elemento
launchMode
.
Há cinco modos de inicialização que podem ser atribuídos ao atributo launchMode
:
"standard"
- O modo padrão. O sistema cria uma nova instância da atividade na tarefa em que foi iniciado e encaminha a intent a ele. A atividade pode ser instanciadas várias vezes, cada instância pode pertencer a tarefas diferentes, e uma tarefa pode ter várias instâncias.
"singleTop"
- Se uma instância da atividade já existir na parte de cima da tarefa atual,
o sistema encaminhará o intent para essa instância por meio de uma chamada para o
onNewIntent()
em vez de criar uma nova instância da atividade. A atividade é instanciadas várias vezes, cada instância pode pertencer a tarefas diferentes, e uma tarefa pode ter várias instâncias, mas somente se a atividade no topo da backstack não é uma instância existente da atividade).
Por exemplo, suponha que a backstack de uma tarefa consista na atividade raiz A com atividades B, C e D no topo (de modo que a pilha é A-B-C-D, com D no topo). Uma intent chega para uma atividade do tipo D. Se D tiver a inicialização
"standard"
padrão , uma nova instância da classe é iniciada e a pilha se torna A-B-C-D-D. No entanto, se o modo de inicialização de D for"singleTop"
, a instância existente de D será recebe a intent poronNewIntent()
, porque está no topo da pilha, e a pilha permanece do tipo A-B-C-D. Se, por outro lado, intent chega para uma atividade do tipo B, então uma nova instância de B é adicionada a pilha, mesmo que o modo de inicialização seja"singleTop"
."singleTask"
- O sistema cria a atividade na raiz de uma nova tarefa ou localiza a
atividade em uma tarefa existente com a mesma afinidade. Se uma instância do
atividade já existe, o sistema encaminha a
para a instância atual por meio de uma chamada ao próprio
onNewIntent()
em vez de criar uma nova instância. Enquanto isso, as atividades sobre ele serão destruídas. .
"singleInstance"
.- O comportamento é o mesmo que para
"singleTask"
, exceto pelo fato de o sistema não iniciar nenhum outro na tarefa que contém a instância. A atividade é sempre o único membro da tarefa. Todas as atividades iniciadas por esta serão abertas em em uma tarefa separada.
"singleInstancePerTask"
.- A atividade só pode ser executada como a atividade raiz da tarefa, a primeira
atividade que criou a tarefa e, portanto, só pode haver uma instância
dessa atividade em uma tarefa. Em contraste com o modo de inicialização
singleTask
, este atividade pode ser iniciada em várias instâncias em tarefas diferentes se aFLAG_ACTIVITY_MULTIPLE_TASK
ouFLAG_ACTIVITY_NEW_DOCUMENT
é definida.
Como outro exemplo, o app de navegador do Android declara que o navegador da Web
a atividade sempre é aberta na própria tarefa especificando a singleTask
.
modo de inicialização no <activity>
. Isso significa que, se o seu aplicativo emitir uma intent para abrir o aplicativo
Navegador, a atividade dele não é colocada na mesma tarefa que seu app. Em vez disso,
uma nova tarefa é iniciada para o navegador ou, se o navegador já tiver uma tarefa
sendo executada em segundo plano, essa tarefa é colocada em prática para lidar com o novo
intenção.
Não importa se uma atividade começa em uma nova tarefa ou na mesma tarefa
a atividade que a iniciou, o botão Voltar e o gesto sempre levam o
usuário à atividade anterior. No entanto, se você iniciar uma atividade que
especifica
o modo de inicialização singleTask
e uma instância dessa atividade existe em um
em segundo plano, ela será colocada em primeiro plano. Neste ponto,
a backstack inclui todas as atividades da tarefa apresentadas no
topo da pilha. A Figura 4 mostra esse tipo de cenário.
Para mais informações sobre como usar os modos de inicialização no arquivo de manifesto, consulte a
Documentação do elemento <activity>
.
Definir modos de inicialização usando flags de intent
Ao iniciar uma atividade, é possível modificar a associação padrão de uma atividade
à tarefa incluindo sinalizações na intent entregue ao
startActivity()
As sinalizações que podem ser usadas para modificar o comportamento padrão são as seguintes:
FLAG_ACTIVITY_NEW_TASK
O sistema inicia a atividade em uma nova tarefa. Se uma tarefa já estiver em execução para o iniciada, essa tarefa é colocada em primeiro plano com último estado restaurado, e a atividade recebe a nova intent
onNewIntent()
Isso produz o mesmo comportamento que o
"singleTask"
. Valor discutido:launchMode
na seção anterior.FLAG_ACTIVITY_SINGLE_TOP
Se a atividade iniciada for a atual, na parte superior da parte de trás pilha, a instância atual recebe uma chamada para
onNewIntent()
em vez de criar uma nova instância da atividade.Isso produz o mesmo comportamento que o
"singleTop"
. ValorlaunchMode
discutido na seção anterior.FLAG_ACTIVITY_CLEAR_TOP
Se a atividade iniciada já estiver em execução na tarefa atual, então, em vez de iniciar uma nova instância dessa atividade, sistema destrói todas as outras atividades acima dele. A intenção é entregue à instância retomada da atividade, agora por cima, por meio de
onNewIntent()
:Não há valor para o atributo
launchMode
que produza esse comportamento.FLAG_ACTIVITY_CLEAR_TOP
é mais frequentemente usado em conjunto comFLAG_ACTIVITY_NEW_TASK
. Quando usadas juntas, essas sinalizações localizar uma atividade existente em outra tarefa e colocá-la em uma posição onde ele pode responder à intent.
Processar afinidades
Uma afinidade indica qual tarefa uma atividade "prefere" a que pertencer. De por padrão, todas as atividades do mesmo app têm afinidade entre si: eles "preferem" estejam na mesma tarefa.
Porém, você pode modificar a afinidade padrão de uma atividade. Atividades definidas em apps diferentes podem compartilhar uma afinidade, e as atividades definidas no mesmo app diferentes afinidades de tarefas podem ser atribuídas.
É possível modificar a afinidade de uma atividade usando o taskAffinity
.
atributo do <activity>
.
O atributo taskAffinity
usa um valor de string que precisa ser diferente de
o nome do pacote padrão
declarado no <manifest>
, porque o sistema usa esse nome para identificar a tarefa padrão
afinidade pelo app.
A afinidade surge em duas circunstâncias:
Quando a intent que inicia uma atividade contém o
FLAG_ACTIVITY_NEW_TASK
.Por padrão, uma nova atividade é iniciada na tarefa da atividade chamava
startActivity()
Ela é enviada para a mesma backstack que o autor da chamada.No entanto, se a intent transmitida para
startActivity()
contiver aFLAG_ACTIVITY_NEW_TASK
o sistema procura uma tarefa diferente para hospedar a nova atividade. Muitas vezes, essa é uma nova tarefa. No entanto, não precisa ser. Se houver tarefa existente com a mesma afinidade que a nova atividade, a atividade é iniciado nessa tarefa. Caso contrário, iniciará uma nova tarefa.Se essa sinalização fizer com que uma atividade inicie uma nova tarefa e o usuário usar a botão home ou gesto para sair, deve haver uma maneira de o usuário sair dele. voltar para a tarefa. Algumas entidades, como o gerenciador de notificações, sempre iniciar atividades em uma tarefa externa, nunca como parte da própria, então a
FLAG_ACTIVITY_NEW_TASK
sempre será colocada nas intents transmitidasstartActivity()
.Se uma entidade externa que pudesse use essa flag pode invocar sua atividade, verifique se o usuário tem uma maneira independente de voltar a tarefa iniciada, como um ícone na tela de início, em que a atividade raiz a tarefa tem
CATEGORY_LAUNCHER
filtro de intent. Para mais informações, consulte a seção sobre como iniciar tarefas.Quando uma atividade tem a
allowTaskReparenting
dela. definido como"true"
.Nesse caso, a atividade pode ser movida da tarefa iniciada para a tarefa em que está uma afinidade quando essa tarefa fica em primeiro plano.
Por exemplo, suponha que uma atividade que informe condições climáticas em cidades selecionadas é definido como parte de um app de viagens. Ele tem a mesma afinidade que outras atividades no mesmo aplicativo, a afinidade de aplicativo padrão, e pode assumir um novo pai com esse atributo.
Quando uma de suas atividades inicia o atividade de previsão do tempo, ela inicialmente pertence à mesma tarefa atividades. No entanto, quando a tarefa do app de viagens fica em primeiro plano, a a atividade de previsão do tempo é reatribuída a essa tarefa e exibida dentro dela.
Limpar a backstack
Se o usuário sair de uma tarefa por muito tempo, o sistema limpará a tarefa de todos exceto a atividade raiz. Quando o usuário retorna à tarefa, somente a atividade raiz é restaurada. O sistema se comporta dessa forma com base suposição de que, depois que um por muito tempo os usuários abandonaram o que estavam fazendo antes e estão retornando à tarefa para começar algo novo.
Há alguns atributos de atividade que podem ser usados para modificar esse comportamento:
alwaysRetainTaskState
- Quando esse atributo é definido como
"true"
na atividade raiz de uma tarefa, o comportamento padrão que acabamos de descrever não acontece. A tarefa retém todos atividades na pilha mesmo após um longo período. clearTaskOnLaunch
Quando esse atributo é definido como
"true"
na atividade raiz de uma tarefa, a tarefa é apagado para a atividade raiz sempre que o usuário sai da tarefa e retorna a ele. Em outras palavras, é o oposto dealwaysRetainTaskState
: A o usuário sempre retorna à tarefa em seu estado inicial, mesmo depois de sair do a tarefa só por um momento.finishOnTaskLaunch
Esse atributo é como
clearTaskOnLaunch
, mas opera em uma única atividade, não em uma tarefa inteira. Também pode causar qualquer atividade a ser concluída, exceto a atividade raiz. Quando ele está definido como"true"
, a atividade permanecerá como parte da tarefa somente na sessão atual. Se o usuário sair e voltar à tarefa, ela não estará mais presente.
Iniciar uma tarefa
É possível configurar uma atividade como ponto de entrada para uma tarefa atribuindo a ela uma intent
com "android.intent.action.MAIN"
como a ação especificada e
"android.intent.category.LAUNCHER"
como a categoria especificada:
<activity ... >
<intent-filter ... >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
...
</activity>
Um filtro de intent desse tipo faz com que um ícone e um rótulo para a atividade no Acesso rápido aos apps, oferecendo aos usuários uma maneira de iniciar a atividade e retorne à tarefa criada a qualquer momento após a inicialização.
Essa segunda habilidade é importante. Os usuários precisam conseguir sair da tarefa e
volte a ela mais tarde usando este inicializador de atividades. Por isso, use apenas
os dois
modos de inicialização que marcam as atividades como sempre iniciando uma tarefa, "singleTask"
e "singleInstance"
, quando a atividade tem uma
ACTION_MAIN
e um
CATEGORY_LAUNCHER
filtro.
Imagine, por exemplo, o que aconteceria se o filtro estivesse ausente: um
a intent inicia uma atividade "singleTask"
, iniciando uma nova tarefa, e o usuário
passa algum tempo trabalhando nessa tarefa. Em seguida, o usuário usa o botão home ou
gesto. A tarefa será enviada para o segundo plano e não ficará visível. Agora, o usuário
não tem como retornar à tarefa porque não está representada no aplicativo
acesso rápido.
Nos casos em que você não quer que o usuário possa retornar a um
atividade, defina a propriedade <activity>
finishOnTaskLaunch
do elemento
para "true"
. Para saber mais, consulte a seção sobre como limpar a backstack.
Outras informações sobre como as tarefas e atividades são representadas e gerenciadas na tela "Recentes" está disponível em Recentes tela.