Qual é a diferença entre FragmentPagerAdapter e FragmentStatePagerAdapter?

375

Qual é a diferença entre FragmentPagerAdaptere FragmentStatePagerAdapter?

Sobre FragmentPagerAdaptero guia do Google diz:

Esta versão do pager é melhor para uso quando há um punhado de fragmentos estáticos tipicamente mais para serem paginados, como um conjunto de guias. O fragmento de cada página visitada pelo usuário será mantido na memória, embora sua hierarquia de exibição possa ser destruída quando não estiver visível. Isso pode resultar no uso de uma quantidade significativa de memória, pois as instâncias de fragmento podem manter uma quantidade arbitrária de estado. Para conjuntos maiores de páginas, considere FragmentStatePagerAdapter.

E sobre FragmentStatePagerAdapter:

Essa versão do pager é mais útil quando há um grande número de páginas, funcionando mais como uma exibição de lista. Quando as páginas não estão visíveis para o usuário, seu fragmento inteiro pode ser destruído, mantendo apenas o estado salvo desse fragmento. Isso permite que o pager mantenha muito menos memória associada a cada página visitada em comparação com FragmentPagerAdaptero custo de potencialmente mais sobrecarga ao alternar entre as páginas.

Então, eu tenho apenas 3 fragmentos. Mas todos eles são módulos separados com uma grande quantidade de dados.

Fragment1lida com alguns dados (nos quais os usuários inserem) e os passa por atividade Fragment2, o que é simples ListFragment. Fragment3também é um ListFragment.

Então, minhas perguntas são : Qual adaptador devo usar? FragmentPagerAdapterou FragmentStatePagerAdapter?

AlexMomotov
fonte
2
Eu acho que ter apenas 3 fragmentos qualifica você a usar o FragmentPagerAdapter. As guias desses fragmentos provavelmente serão todas visíveis simultaneamente.
IgorGanapolsky
2
este post salvou minha 5-6 horas porque eu uso tipo errado de adaptador
Nantaphop
11
A resposta a esta pergunta lança mais uma pergunta: stackoverflow.com/questions/9156406/…
Piyush Kukadiya
existe FragmentPagerAdaptere FragmentStatePagerAdaptermas o que é FragmentStateAdapter?
the_prole

Respostas:

292

Como dizem os médicos, pense dessa maneira. Se você fosse fazer um aplicativo como um leitor de livros, não desejaria carregar todos os fragmentos na memória de uma só vez. Você gostaria de carregar e destruir Fragmentsenquanto o usuário lê. Nesse caso, você usará FragmentStatePagerAdapter. Se você está apenas exibindo 3 "guias" que não contêm muitos dados pesados ​​(como Bitmaps), FragmentPagerAdapterpode ser bom para você. Além disso, lembre-se de que, ViewPagerpor padrão, carregará 3 fragmentos na memória. O primeiro que Adaptervocê mencionar pode destruir a Viewhierarquia e recarregá-lo quando necessário, o segundo Adaptersalva apenas o estado do Fragmente o destrói completamente; se o usuário voltar a essa página, o estado será recuperado.

Emmanuel
fonte
Eu tenho vários botões e TextViews no Fragment1 e ListView que geram itens dinamicamente no Fragment2 e Fragment3. Você acha que é uma boa idéia usar o FragmentStatePagerAdapter e armazenar todos os dados em Activity, passando-os para os Fragments via Bundle?
AlexMomotov 12/09/2013
2
@AlexMomotov As visualizações no layout do Fragment não têm nada a ver com a escolha do FragmentStatePagerAdapter. A questão aqui é a quantidade de fragmentos que serão paginados.
IgorGanapolsky 28/05
11
Então, basicamente, não há nada a favor de FragmentPagerAdapterusá-lo.
Tomasz Mularczyk
3
A vantagem do @Tomasz FragmentPagerAdapteré que a alternância entre fragmentos pode ser muito mais rápida, pois os Fragmentobjetos reais não precisam ser reconstruídos a cada vez. Por outro lado, isso acabaria usando mais memória mantendo os objetos de fragmento na memória.
Richard Le Mesurier
Eu tenho 3 guias / páginas (cada uma delas mostra um WebView), então usei o FragmentPagerAdapter . No entanto, a última página ainda é redesenhada quando deslizo para ela a partir da primeira página. Para resolver isso, eu usei viewPager.setOffscreenPageLimit(2).
ban-geoengineering
131
  • FragmentPagerAdapterarmazena todo o fragmento na memória e pode aumentar a sobrecarga da memória se uma grande quantidade de fragmentos for usada ViewPager.

  • Ao contrário de seu irmão, FragmentStatePagerAdapterapenas armazena oStInstanceState dos fragmentos e destrói todos os fragmentos quando eles perdem o foco.

  • Portanto, FragmentStatePagerAdapterdeve ser usado quando tivermos que usar fragmentos dinâmicos, como fragmentos com widgets, pois seus dados podem ser armazenados no arquivo savedInstanceState.Também não afetará o desempenho, mesmo que haja um grande número de fragmentos.

  • Pelo contrário, seu irmão FragmentPagerAdapterdeve ser usado quando precisamos armazenar todo o fragmento na memória.

  • Quando digo que todo o fragmento é mantido na memória, suas instâncias não serão destruídas e criariam uma sobrecarga de memória. Portanto, é recomendável usar FragmentPagerAdaptersomente quando houver um número baixo de fragmentos ViewPager.

  • Seria ainda melhor se os fragmentos fossem estáticos, pois não estariam tendo grande quantidade de objetos cujas instâncias seriam armazenadas.

Para ser mais detalhado,

FragmentStatePagerAdapter:

  • com FragmentStatePagerAdapter , seu fragmento desnecessário é destruído. Uma transação é comprometida para remover completamente o fragmento da sua atividade FragmentManager.

  • O estado FragmentStatePagerAdaptervem do fato de que ele salvará o seu fragmento Bundlede savedInstanceStatequando é destruído. Quando o usuário voltar, o novo fragmento será restaurado usando o estado do fragmento.

FragmentPagerAdapter:

  • Por comparação FragmentPagerAdapter, nada é do tipo. Quando o fragmento não é mais necessário. FragmentPagerAdapterchama detach(Fragment)a transação em vez de remove(Fragment).

  • Isso destrói a visão do fragmento, mas deixa viva a instância do fragmento no FragmentManager. Para que os fragmentos criados no FragmentPagerAdapternunca sejam destruídos.

Steve
fonte
2
Por que você tem 2 respostas?
Jared Burrows
qual é o benefício de manter fragmentos inteiros na memória?
Tomasz Mularczyk
4
@ Tomk: se o próximo fragmento já estiver instanciado (ou seja, FragmentPagerAdapter), ele estará pronto para renderizar quando você o deslizar para que a animação seja mais suave. Com FragmentStatePagerAdapter, a próxima instância de fragmento pode não existir até você deslizar para ela e, se for um fragmento grande e caro para criar, você poderá ver uma gagueira na animação. É uma questão de desempenho versus consumo de memória.
Dalbergia 21/07
11
@Jared Burrows bcoz é apenas AnswerText que é bom para pequenas e estáticas respostas eo outro é AnswerStateText que é por respostas maiores e dinâmicas
Simples Fellow
48

Aqui está um ciclo de vida de log de cada fragmento no ViewPagerqual possui 4 fragmentos eoffscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Vá para o Fragmento1 (atividade de lançamento)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Ir para Fragment2

Fragment3: onCreateView
Fragment3: onStart

Ir para Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart

Ir para Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Vá para o Fragmento1 (atividade de lançamento)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Ir para Fragment2

Fragment3: onCreateView
Fragment3: onStart

Ir para Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart

Ir para Fragment4

Fragment2: onStop
Fragment2: onDestroyView

Conclusão : FragmentStatePagerAdapterchama onDestroyquando o fragmento é superado offscreenPageLimitenquanto FragmentPagerAdapternão.

Nota : Eu acho que devemos usar FragmentStatePagerAdapterpara um ViewPagerque tenha muitas páginas, porque será bom para o desempenho.

Exemplo de offscreenPageLimit:

Se formos para Fragment3, ele vai Detroy Fragment1 (ou Fragment5 se tem) porque offscreenPageLimit = 1. Se definirmos offscreenPageLimit > 1, não destruirá.
Se neste exemplo, definirmos offscreenPageLimit=4, não haverá diferença entre usar FragmentStatePagerAdapterou FragmentPagerAdapterporque o Fragment nunca chama onDestroyVieweonDestroy quando alteramos a guia

Demonstração do Github aqui

Phan Van Linh
fonte
Uma ótima maneira de concluir!
Rahul Rastogi 28/10/19
boa explicação
gourav singhal 27/11/19
11
Boa explicação. Você disse que usar o FragmentStatePagerAdapter ao ter muitas páginas é bom para o desempenho. Você quis dizer que é bom para economizar memória? O objetivo, no meu entender, é preservar a memória em caso de várias instâncias possíveis do Fragment - para que o desempenho seja o benefício implícito; o objetivo explícito é preservar a memória
Hatzil 11/04
38

Algo que não é explicitamente dito na documentação ou nas respostas nesta página (mesmo que implícitas pelo @Naruto), é que FragmentPagerAdapter não atualizará os Fragmentos se os dados no Fragmento mudarem, pois mantém o Fragmento na memória.

Portanto, mesmo se você tiver um número limitado de fragmentos para exibir, se desejar atualizar seus fragmentos (por exemplo, execute novamente a consulta para atualizar o listView no fragmento), será necessário usar FragmentStatePagerAdapter.

Meu argumento aqui é que o número de fragmentos e se são ou não semelhantes nem sempre é o aspecto principal a considerar. Se seus fragmentos são dinâmicos ou não, também é fundamental.

JDenais
fonte
Digamos que eu tenha 2 fragmentos, 1 reciclagem no fragmento A, quando clico em um item, ele altera o conteúdo do fragmento B, digamos fragB.setText ("blablabla"). Eu deveria usar o estado pagerthen?
Ced
Não tenho certeza, mas eu diria que sim. Apenas tente os dois, é realmente fácil e rápido alterar seu código de um para outro de qualquer maneira.
JDenais
@JDenais Tem certeza de que está correto? Estou usando FragmentPagerAdapterem minha atividade que usa um ViewPager para mostrar dois fragmentos - onde cada fragmento contém uma lista. Minha primeira lista é chamada "Todos os relatórios" e a segunda lista é "Relatórios favoritos". Na primeira lista, se eu tocar no ícone de estrela de um relatório, ele atualizará o banco de dados para alternar o status favorito desse relatório. Depois deslizo e vejo esse relatório com sucesso na interface da segunda lista. Portanto, talvez as instâncias sejam mantidas na memória, mas em alguns casos (por exemplo, o meu), o conteúdo será realmente atualizado corretamente para FragmentPagerAdapter
ban-
14

FragmentPagerAdapterarmazena os dados anteriores que são buscados no adaptador e FragmentStatePagerAdapterobtém o novo valor do adaptador toda vez que ele é executado.

vinay kumar
fonte
4

FragmentStatePagerAdapter = Para acomodar um grande número de fragmentos no ViewPager. Como esse adaptador destrói o fragmento quando ele não está visível para o usuário e apenas o SaveInstanceState do fragmento é mantido para uso posterior. Dessa forma, uma baixa quantidade de memória é usada e um melhor desempenho é entregue no caso de fragmentos dinâmicos.

Dwivedi Ji
fonte
1

FragmentPagerAdapter : o fragmento de cada página visitada pelo usuário será armazenado na memória, embora a exibição seja destruída. Portanto, quando a página estiver visível novamente, a exibição será recriada, mas a instância do fragmento não será recriada. Isso pode resultar em uma quantidade significativa de memória sendo usada. FragmentPagerAdapter deve ser usado quando precisamos armazenar o fragmento inteiro na memória. Chama FragmentPagerAdapter desanexar (fragmento) na transação em vez de remover (fragmento).

FragmentStatePagerAdapter : a instância do fragmento é destruída quando não está visível para o Usuário, exceto o estado salvo do fragmento. Isso resulta no uso de apenas uma pequena quantidade de memória e pode ser útil para manipular conjuntos de dados maiores. Deve ser usado quando precisamos usar fragmentos dinâmicos, como fragmentos com widgets, pois seus dados podem ser armazenados no saveInstanceState. Além disso, não afetará o desempenho, mesmo que haja um grande número de fragmentos.

foroogh.Varmazyar
fonte