Tarefas e a backstack

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.

Figura 1. Uma representação de como cada nova atividade em uma tarefa adiciona um item à pilha de retorno. Quando o usuário toca ou faz um gesto De volta, a atividade atual é destruída, e a atividade anterior ou currículos.

À 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 O super.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

Figura 2. Duas tarefas: a Tarefa B recebe a interação do usuário primeiro plano, enquanto a Tarefa A está em segundo plano, aguardando no currículo.

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:

  1. 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.

  2. 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

Figura 3. Uma única atividade pode ser instanciada diversas vezes.

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:

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:

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:

  1. "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.
  2. "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 por onNewIntent(), 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".

  3. "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.
    .
  4. "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.
  5. "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 a FLAG_ACTIVITY_MULTIPLE_TASK ou FLAG_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.

Figura 4. Uma representação de como uma atividade com inicialização o modo "singleTask" foi adicionado à backstack. Se a atividade já fizer parte de uma tarefa em segundo plano com a própria backstack, então esse toda a backstack também avança, acima da atual tarefa.

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". Valor launchMode 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 com FLAG_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:

  1. 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 a FLAG_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 transmitidas startActivity().

    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.

  2. 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 de alwaysRetainTaskState: 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.

Mais recursos