Dilema: quando usar Fragmentos x Atividades:


786

Eu sei que Activitiessão projetados para representar uma única tela do meu aplicativo, enquanto Fragmentssão projetados para serem layouts de UI reutilizáveis ​​com lógica incorporada dentro deles.

Até pouco tempo atrás, desenvolvi um aplicativo que dizia que eles deveriam ser desenvolvidos. Criei um Activitypara representar uma tela do meu aplicativo e usei Fragments para ViewPageror Google Maps. Eu raramente criei uma ListFragmentou outra interface do usuário que pode ser reutilizada várias vezes.

Recentemente me deparei com um projeto que contém apenas 2 Activitiesum é um SettingsActivitye outro é o MainActivity. O layout do MainActivityé preenchido com muitos fragmentos de interface do usuário ocultos em tela cheia e apenas um é mostrado. Na Activitylógica, existem muitos FragmentTransitionsentre as diferentes telas do aplicativo.

O que eu gostei dessa abordagem é que, como o aplicativo usa um ActionBar, ele permanece intacto e não se move com a animação de alternância de tela, que é o que acontece com a Activityalternância. Isso dá uma sensação mais fluente a essas transições de tela.

Acho que o que estou pedindo é compartilhar sua maneira atual de desenvolvimento com relação a esse tópico. Sei que pode parecer uma pergunta baseada em opinião à primeira vista, mas a considero uma questão de design e arquitetura do Android ... opinião baseada em um.

UPDATE (01.05.2014): Após esta apresentação de Eric Burke da Square , (que devo dizer que é uma ótima apresentação com muitas ferramentas úteis para desenvolvedores de Android. E não tenho nenhuma relação com Square)

http://www.infoq.com/presentations/Android-Design/

De minha experiência pessoal nos últimos meses, descobri que a melhor maneira de construir meus aplicativos é criar grupos de fragmentos que representam um fluxo no aplicativo e apresentam todos esses fragmentos em um Activity. Então, basicamente, você terá o mesmo número de Activitiesem seu aplicativo que o número de fluxos. Dessa forma, a barra de ação permanece intacta em todas as telas do fluxo, mas está sendo recriada na alteração de um fluxo que faz muito sentido. Como Eric Burke afirma e como eu também percebi, a filosofia de usar o mínimo Activitiespossível não é aplicável a todas as situações, porque cria uma confusão no que ele chama de atividade de "Deus".


2

Respostas:


271

Os especialistas dirão: "Quando visualizar a interface do usuário, saberei se devo usar um Activityou um Fragment". No começo, isso não fará sentido, mas, com o tempo, você será capaz de dizer se precisa Fragmentou não.

Há uma boa prática que achei muito útil para mim. Ocorreu-me enquanto tentava explicar algo para minha filha.

Ou seja, imagine uma caixa que representa uma tela. Você pode carregar outra tela nesta caixa? Se você usar uma nova caixa, precisará copiar vários itens da 1ª caixa? Se a resposta for Sim, você deve usá-lo Fragments, porque a raiz Activitypode conter todos os elementos duplicados para poupar tempo ao criá-los, e você pode simplesmente substituir partes da caixa.

Mas não esqueça que você sempre precisa de um contêiner de caixa ( Activity) ou suas peças serão dispersas. Então, uma caixa com peças dentro.

Tome cuidado para não usar mal a caixa. Os especialistas em Android UX aconselham (você pode encontrá-los no YouTube) quando devemos carregar outro explicitamente Activity, em vez de usar um Fragment(como quando lidamos com a Gaveta de Navegação que possui categorias). Depois de se sentir confortável Fragments, você poderá assistir a todos os vídeos deles. Ainda mais, eles são materiais obrigatórios.

Você pode agora olhar para sua interface do usuário e descobrir se precisa de um Activityou de um Fragment? Você recebeu uma nova perspectiva? Eu acho que você fez.


4
você tem um link para o feed do youtube que você mencionou? Pesquisei "especialistas em Android UX" e "Android UX", mas não tenho certeza de quais vídeos você está falando.
me--

2
Não mais, assisti mais de um ano atrás. Procurar oficial desenvolvedor Android falando sobre UX
sandalone

1
Um exemplo de consideração: a atividade tem parentActivity para que possamos sintetizar o backstack ao inserir a partir da notificação, mas não acho que exista tal parentFragment.
Fikr4n


@ToolmakerSteve sim é getParentFragment, mas não é o que eu quis dizer cara, ver developer.android.com/guide/topics/manifest/...
fikr4n

129

Minha filosofia é esta:

Crie uma atividade apenas se for absolutamente necessária. Com a pilha traseira disponibilizada para confirmar várias transações de fragmento, tento criar o mínimo possível de atividades no meu aplicativo. Além disso, a comunicação entre vários fragmentos é muito mais fácil do que o envio de dados entre as atividades.

As transições de atividades são caras, certo? Pelo menos eu acredito que sim - uma vez que a atividade antiga deve ser destruída / pausada / parada, empurrada para a pilha e, em seguida, a nova atividade deve ser criada / iniciada / retomada.

É apenas a minha filosofia desde que os fragmentos foram introduzidos.


2
verdade, mas como você escreveu, às vezes é necessário usar atividades. um exemplo é a tela da câmera, onde é melhor usá-la no modo paisagem. outro exemplo é a tela de configuração mostrada quando você coloca um appWidget personalizado (na "área de trabalho" - o aplicativo iniciador).
desenvolvedor android

Obrigado por responder e compartilhar sua experiência. Então, você acha que é uma boa prática no android limitar o aplicativo a uma atividade e usar o fragmento em todas as telas, se a arquitetura do aplicativo permitir?
Emil Adz

1
Então, como você resolve a questão dos fragmentos que precisam passar um para o outro "estado"? Todo o estado em todos os seus fragmentos precisa viver em uma atividade, caso contrário você é forçado a usar um singleton.
Mr_E 27/09/16

36
Não estou convencido de que a comunicação entre vários fragmentos seja muito mais fácil do que enviar dados entre as atividades.
Denny

3
Pelo menos, onActivityResult()é mais seguro e fácil do que os retornos de chamada dos fragmentos.
CoolMind 6/10

59

Bem, de acordo com as palestras do Google (talvez aqui , não me lembro), você deve considerar o uso de fragmentos sempre que possível, pois isso facilita a manutenção e o controle do seu código.

No entanto, acho que, em alguns casos, pode ficar muito complexo, pois a atividade que hospeda os fragmentos precisa navegar / se comunicar entre eles.

Eu acho que você deve decidir por si mesmo o que é melhor para você. Geralmente não é tão difícil converter uma atividade em um fragmento e vice-versa.

Eu criei um post sobre esse dillema aqui , se você quiser ler mais.


5
Obrigado por responder e compartilhar sua experiência. Então, você acha que é uma boa prática no android limitar o aplicativo a uma atividade e usar o fragmento em todas as telas, se a arquitetura do aplicativo permitir?
Emil Adz

Depende do projeto, mas se for muito complicado para você, você também pode se separar para várias atividades. Não tenha medo de usar nenhum dos métodos. Você também pode usar os dois. Talvez às vezes seja muito difícil você usar fragmentos em vez de atividades. Eu acho que você deve tentar usar fragmentos, mas não forçá-lo a estar em toda parte se ele fica muito em seu caminho ...
desenvolvedor android

e se eu quiser manter esse efeito da ActionBar intacto e todo o conteúdo estiver sendo alterado? É possível conseguir isso com as atividades?
Emil Adz


27

Por que prefiro Fragmento a Atividade em TODOS OS CASOS.

  • Atividade é cara. No Fragmento, as visualizações e os estados de propriedade são separados - sempre que um fragmento estiver inserido backstack, suas visualizações serão destruídas. Assim, você pode empilhar muito mais fragmentos que atividade.

  • Backstackmanipulação. Com FragmentManager, é fácil limpar todos os fragmentos, inserir mais do que em fragmentos e etcs. Mas para Activity, será um pesadelo manipular essas coisas.

  • Um ciclo de vida muito previsível . Contanto que a Atividade do host não seja reciclada. os fragmentos no backstack não serão reciclados. Portanto, é possível usar FragmentManager::getFragments()para encontrar fragmentos específicos (não incentivados).


Olá, li seu comentário sobre as vantagens do Frag sobre o Act. Você tem algum projeto para mostrar o mesmo no seu Github Repo?
Umang ßürmån

24

Desde o Jetpack , o aplicativo de atividade única é a arquitetura preferida. Útil especialmente com o componente de arquitetura de navegação .

fonte


Obrigado por isso!
Simão Garcia

1
Eu li sobre o Jetpack pela primeira vez hoje. :) Criamos aplicativos de atividade única desde que os fragmentos foram introduzidos. A atividade múltipla é muito mais complicada.
O incrível Jan

1
@TheincredibleJan Você está certo, única atividade App arquitetura era melhor solução muito antes de Jetpack
Francis

12

Na minha opinião, não é realmente relevante. O fator chave a considerar é

  1. com que frequência você reutilizará partes da interface do usuário (menus por exemplo),
  2. o aplicativo também é para tablets?

O principal uso de fragmentos é criar atividades de vários painéis, o que o torna perfeito para aplicativos responsivos para Tablet / Telefone.


Eu diria que o principal uso de fragmentos é criar visualizações personalizadas sem pensar nelas como visualizações personalizadas. é o que acontece de qualquer maneira. Fragmentos mostrados originalmente no Google como uma maneira prática de criar aplicativos responsivos para tablets, para que você possa colocá-los em atividades diferentes, se quiser. uma maneira de anexar código a uma visualização, mais ou menos, e mantê-los aderentes onde você desejar (sem criar visualizações personalizadas).
Lassi Kinnunen

11

Não se esqueça que uma atividade é o bloco / componente do aplicativo que pode ser compartilhado e iniciado através do Intent! Portanto, cada atividade em seu aplicativo deve resolver apenas um tipo de tarefa. Se você tiver apenas uma tarefa em seu aplicativo, acho que precisará de apenas uma atividade e muitos fragmentos, se necessário. Claro que você pode reutilizar fragmentos em atividades futuras que resolvem outras tarefas. Essa abordagem será uma separação clara e lógica de tarefas. E você não precisa manter uma atividade com diferentes parâmetros de filtro de intenção para diferentes conjuntos de fragmentos. Você define tarefas no estágio de design do processo de desenvolvimento com base nos requisitos.


Em nossas aplicações, o único tipo de tarefa da atividade é segurar a gaveta de navegação para inserir os diferentes fragmentos. :) Por que devo lidar com intenções de fragmentos? É claro e lógico manter uma referência estática a uma classe de dados "global" para dados globais e passar alguns valores para um método de instância de criação de um fragmento.
O incrível Jan

9

Há mais do que você imagina, é preciso lembrar que uma atividade lançada não destrói implicitamente a atividade de chamada. Claro, você pode configurá-lo de forma que o usuário clique em um botão para ir para uma página, inicie a atividade dessa página e destrua a atual. Isso causa muita sobrecarga. O melhor guia que posso dar é:

** Inicie uma nova atividade apenas se fizer sentido ter a atividade principal e esta aberta ao mesmo tempo (pense em várias janelas).

Um ótimo exemplo de quando faz sentido ter várias atividades é o Google Drive. A atividade principal fornece um explorador de arquivos. Quando um arquivo é aberto, uma nova atividade é iniciada para visualizar esse arquivo. Você pode pressionar o botão de aplicativos recentes, que permitirá retornar ao navegador sem fechar o documento aberto e, em seguida, talvez abrir outro documento paralelamente ao primeiro.


Re "Inicie uma nova atividade apenas se fizer sentido ter a atividade principal e esta aberta ao mesmo tempo (pense em várias janelas)." Acho que não. Essa situação é bem resolvida usando fragmentos attach / detachmétodos.
precisa saber é o seguinte

7

O que eu fiz: usando menos fragmento quando possível. Infelizmente, é possível em quase todos os casos. Então, acabo com muitos fragmentos e um pouco de atividades. Algumas desvantagens que eu percebi:

  • ActionBar& Menu: Quando o fragmento 2 possui um título, menu diferente,
    será difícil lidar com isso. Ex: ao adicionar um novo fragmento, você pode alterar o título da barra de ação, mas, quando pop-lo, backstacknão há como restaurar o título antigo. Você pode precisar de uma barra de ferramentas em cada fragmento para este caso, mas, acredite, você gastará mais tempo.
  • Quando precisamos startForResult, a atividade tem, mas o fragmento não.
  • Não tem animação de transição por padrão

Minha solução para isso é usar uma atividade para quebrar um fragmento dentro. Portanto, temos barra de ação, menu startActivityForResult, animação, ...


1
Pontos muito úteis, obrigado. Você pode esclarecer " uma atividade para quebrar um fragmento "? Você fez uma atividade separada para cada fragmento? Se sim, você precisa do Fragment?
precisa

3
existe uma maneira de restaurar o título e outras coisas. use getSupportFragmentManager().addOnBackStackChangedListenerpara adicionar um ouvinte. obtenha o fragmento atual no ouvinte e defina o título e outras coisas.
babay

4

A grande vantagem de uma fragmentatividade excessiva é que, o código usado para fragmento pode ser usado para atividades diferentes. Assim, ele fornece reutilização de código no desenvolvimento de aplicativos.


3
Quão? Você poderia fornecer algum exemplo, por favor?
sofs1

1
@ sofs1 Sua pergunta não faz muito sentido. Qualquer código em um fragmento permanece o mesmo, independentemente da atividade em que o fragmento é instatado.
O incrível Jan

@TheincredibleJan Mas não poderíamos dizer também "Qualquer código em uma atividade permanece o mesmo, independentemente de qual atividade a segunda atividade é instanciada". Eu não vejo a diferença.
iforce2d

3

usar uma actividade por aplicação para fornecer base para fragment utilização fragmentpara a tela, fragmentssão peso de lite , em comparação com activites fragmentos são reutilizáveis fragmentos são melhor adequados para a aplicação que suporta tanto telefone & pastilha


2

Você é livre para usar um desses.
Basicamente, você deve avaliar qual é o melhor para seu aplicativo. Pense em como você gerenciará o fluxo de negócios e como armazenar / gerenciar preferências de dados.

Pense em como os Fragments armazenam dados de lixo. Ao implementar o fragmento, você tem uma raiz de atividade para preencher com fragmento (s). Portanto, se você está tentando implementar muitas atividades com muitos fragmentos, deve considerar o desempenho em seu aplicativo, porque está manipulando (fala grosseiramente) o ciclo de vida de dois contextos, lembre-se da complexidade.

Lembre-se: devo usar fragmentos? Por que não deveria?

Saudações.


1

Eu uso fragmentos para melhor experiência do usuário. Por exemplo, se você possui um botão e deseja executar, digamos um serviço da web ao clicar nele, anexo um fragmento à atividade pai.

if (id == R.id.forecast) {

    ForecastFragment forecastFragment = new ForecastFragment();
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.main_content, forecastFragment);
    ft.addToBackStack("backstack");
    forecastFragment.setArguments(b);
    ft.commit();
}

Dessa forma, o usuário não precisará se mudar para outra atividade.

Em segundo lugar, prefiro os fragmentos porque você pode lidar com eles facilmente durante a rotação.


O que torna esse exemplo uma melhor experiência do usuário? Como eles saberão (ou se importarão) que estão fazendo uma atividade ou um fragmento?
iforce2d

1

Depende do que você deseja construir realmente. Por exemplo, o navigation drawerusa fragmentos. As guias também são usadas fragments. Outra boa implementação, é onde você tem um listview. Quando você gira o telefone e clica em uma linha, a atividade é mostrada na metade restante da tela. Pessoalmente, eu uso fragmentse fragment dialogs, como é mais profissional. Além disso, eles são manuseados com mais facilidade na rotação.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.