FragmentPagerAdapter ve FragmentStatePagerAdapter arasındaki fark nedir?


375

Arasındaki fark nedir FragmentPagerAdapterve FragmentStatePagerAdapter?

Hakkında FragmentPagerAdapterGoogle'ın kılavuzu diyor ki:

Çağrı cihazının bu versiyonu, bir sekme seti gibi, sayfalanacak tipik olarak bir avuç daha statik parça olduğunda kullanım için en iyisidir. Kullanıcının ziyaret ettiği her sayfanın parçası bellekte tutulur, ancak görünüm hiyerarşisi görünür olmadığında yok edilebilir. Bu, parça örnekleri keyfi miktarda duruma dayanabileceğinden önemli miktarda bellek kullanımına neden olabilir. Daha büyük sayfa grupları için düşünün FragmentStatePagerAdapter.

Ve hakkında FragmentStatePagerAdapter:

Çağrı cihazının bu sürümü, daha çok liste görünümü gibi çalışan çok sayıda sayfa olduğunda daha kullanışlıdır. Sayfalar kullanıcı tarafından görülemediğinde tüm parçaları yok edilebilir ve yalnızca o parçanın kayıtlı durumu korunabilir. Bu, çağrı cihazının, FragmentPagerAdaptersayfalar arasında geçiş yaparken potansiyel olarak daha fazla ek yüke kıyasla, ziyaret edilen her bir sayfa ile ilişkili çok daha az bellek tutmasını sağlar .

Yani sadece 3 parçam var. Ancak hepsi, büyük miktarda veri içeren ayrı modüllerdir.

Fragment1(kullanıcıların girdiği) bazı verileri işler ve etkinlik yoluyla iletir Fragment2, bu da basittir ListFragment. Fragment3aynı zamanda bir ListFragment.

Sorularım : Hangi adaptörü kullanmalıyım? FragmentPagerAdapterveya FragmentStatePagerAdapter?


2
Ben sadece 3 Fragment sahip FragmentPagerAdapter kullanmak için nitelikli olduğunu düşünüyorum. Bu Fragmanların sekmeleri muhtemelen aynı anda görünecektir.
IgorGanapolsky

2
Bu yazı benim 5-6 saatimi kurtardı çünkü yanlış adaptör kullanıyorum
Nantaphop

1
Bu sorunun cevabı bir soru daha atıyor stackoverflow.com/questions/9156406/…
Piyush Kukadiya

var FragmentPagerAdapterve FragmentStatePagerAdapternedir FragmentStateAdapter?
the_prole

Yanıtlar:


292

Dokümanların dediği gibi, bu şekilde düşünün. Kitap okuyucusu gibi bir uygulama yapacaksanız, tüm parçaları bir kerede belleğe yüklemek istemezsiniz. FragmentsKullanıcı okudukça yüklemek ve yok etmek istiyorsunuz . Bu durumda kullanacaksınız FragmentStatePagerAdapter. Çok fazla ağır veri içermeyen (") 3" sekme "görüntülüyorsanız Bitmaps, FragmentPagerAdaptersize uygun olabilir. Ayrıca, ViewPagervarsayılan olarak belleğe 3 parça yükleyeceğini unutmayın . Bahsettiğiniz ilk Adapterşey Viewhiyerarşiyi yok edebilir ve gerektiğinde yeniden yükleyebilir, ikincisi Adaptersadece durumunu kaydeder Fragmentve tamamen yok eder, kullanıcı daha sonra bu sayfaya geri gelirse, durum alınır.


Fragment1 ve Fragment3 dinamik olarak öğeleri üretmek Fragment1 ve ListView birden çok düğme ve TextViews var. FragmentStatePagerAdapter kullanmanın ve tüm verileri Etkinlik'te depolamanın Paket ile Parçalara iletmenin iyi bir fikir olduğunu düşünüyor musunuz?
AlexMomotov

2
@AlexMomotov Fragment'ın mizanpajındaki görünümlerin FragmentStatePagerAdapter seçimiyle ilgisi yoktur. Buradaki soru, sayfalanacak Parçaların miktarıdır.
IgorGanapolsky

1
Yani temelde FragmentPagerAdapteronu kullanmaktan yana hiçbir şey yok .
Tomasz Mularczyk

3
@Tomasz, FragmentPagerAdaptergerçek Fragmentnesnelerin her seferinde yeniden oluşturulmasına gerek olmadığından , parçalar arasında geçiş yapmanın çok daha hızlı olabilmesidir. Öte yandan, bu, parça nesnelerini bellekte tutan daha fazla bellek kullanılmasıyla sonuçlanacaktır.
Richard Le Mesurier

3 Sekme / sayfa (her bir WebView göstermek), bu yüzden FragmentPagerAdapter kullandık . Ancak, ilk sayfadan kaydırdığımda son sayfa yeniden çiziliyor. Bunu çözmek için kullandım viewPager.setOffscreenPageLimit(2).
ban-geoengineering

131
  • FragmentPagerAdaptertüm parçayı bellekte saklar ve çok miktarda parça kullanılırsa bellek ek yükünü artırabilir ViewPager.

  • Kardeşinin aksine, FragmentStatePagerAdaptersadece kayıtlıInstanceState parçasını saklar ve odağı kaybettiklerinde tüm parçaları yok eder.

  • Bu nedenle FragmentStatePagerAdapter, verileri parçacıklarda saklanabileceğinden, widget'lı parçalar gibi dinamik parçaları kullanmamız gerektiğinde kullanılmalıdır. savedInstanceStateAyrıca çok sayıda parça olsa bile performansı etkilemez.

  • Aksine FragmentPagerAdapter, tüm parçayı hafızada saklamamız gerektiğinde kardeşi kullanılmalıdır.

  • Bütün parçanın bellekte tutulduğunu söylediğimde, örnekleri yok olmayacak ve bir bellek yükü yaratacaktır. Bu nedenle, FragmentPagerAdapteryalnızca düşük sayıda parça olduğunda kullanılması tavsiye edilir ViewPager.

  • Parçaların statik olması daha iyi olurdu, çünkü örnekleri depolanacak büyük miktarda nesneye sahip olmayacaklardı.

Daha ayrıntılı olmak için,

FragmentStatePagerAdapter:

  • Bir FragmentStatePagerAdapterişlem, parçayı etkinliklerinizden tamamen kaldırmaya kararlıdır FragmentManager.

  • İçindeki durum, FragmentStatePagerAdapterparçanızın imha edildiği andan Bundleitibaren kurtaracağı gerçeğinden savedInstanceStategelir.Kullanıcı geri döndüğünde, parçanın durumu kullanılarak yeni parça geri yüklenir.

FragmentPagerAdapter:

  • Karşılaştırma ile tür FragmentPagerAdapterhiçbir şey yapmaz. yerine işlemi FragmentPagerAdapterçağırır .detach(Fragment)remove(Fragment)

  • Bu, parçanın görüşünü yok eder, ancak parçanın örneğini FragmentManager.so'da canlı bırakır, böylece içinde oluşturulan parçalar FragmentPagerAdapterasla yok olmaz.


2
Neden 2 cevabın var?
Jared Burrows

bütün parçaları hafızada tutmanın faydası nedir?
Tomasz Mularczyk

4
@Tomek: bir sonraki parça zaten somutlaştırılmışsa (örn. FragmentPagerAdapter), hızlıca kaydırdığınızda oluşturmaya hazır olur, böylece kaydırma animasyonu daha düzgün olur. FragmentStatePagerAdapter ile, sonraki parça örneği, siz onu kaydırana kadar mevcut olmayabilir ve oluşturulması pahalı olan büyük bir parça ise, animasyonda bir takılma görebilirsiniz. Bu bir performans meselesi ile bellek tüketimi meselesidir.
Dalbergia

1
@Jared Burrows bcoz biri sadece küçük ve statik cevaplar için iyi olan AnswerText , diğeri ise daha büyük ve dinamik cevaplar için olan AnswerStateText'tir
Simple Fellow

48

ViewPager4 parçalı ve her parçanın günlük yaşam döngüsüoffscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Fragment1'e gidin (başlatma etkinliği)

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

Fragment2'ye git

Fragment3: onCreateView
Fragment3: onStart

Fragment3 şehrine git

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

Fragment4'e git

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Fragment1'e gidin (başlatma etkinliği)

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

Fragment2'ye git

Fragment3: onCreateView
Fragment3: onStart

Fragment3 şehrine git

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

Fragment4'e git

Fragment2: onStop
Fragment2: onDestroyView

Sonuç : FragmentStatePagerAdapterÇağrı onDestroyFragment aşılır offscreenPageLimitiken FragmentPagerAdapterdeğil.

Not : Çok sayfalı bir sayfa FragmentStatePagerAdapteriçin kullanmamız gerektiğini düşünüyorum ViewPagerçünkü performans için iyi olacak.

Örnek bölgesinin offscreenPageLimit:

Biz Fragment3 giderseniz, o olacak (varsa veya Fragment5) Fragment1 detroy çünkü offscreenPageLimit = 1. Biz ayarlarsanız offscreenPageLimit > 1bu alışkanlık yok.
Bu örnekte, biz ayarlarsanız offscreenPageLimit=4, kullanma arasında hiçbir farkı yoktur FragmentStatePagerAdapterya FragmentPagerAdapterParçası çağrı çünkü asla onDestroyViewveonDestroy sekmeyi değiştirdiğimizde

Github demosu burada


Böyle harika bir sonuç!
Rahul Rastogi

güzel açıklama
gourav singhal

1
Güzel açıklama. Çok fazla sayfa varken FragmentStatePagerAdapter kullanmanın performans için iyi olduğunu söylediniz. Bellek tasarrufu için iyi mi demek istediniz? Anladığım kadarıyla amaç, birçok Fragment örneği olması durumunda belleği korumaktır - bu nedenle performans örtük faydadır; açık hedef hafızayı korumaktır
Hatzil

38

Belgelerde veya bu sayfadaki cevaplarda (@Naruto tarafından ima edilmesine rağmen) açıkça söylenmeyen bir şey, Parçanın FragmentPagerAdapteriçindeki veriler değişir, çünkü Parçayı bellekte tutar.

Bu nedenle, görüntülenecek sınırlı sayıda Parçanız olsa bile, parçalarınızı yenilemek istiyorsanız (örneğin, Parçideki listView öğesini güncellemek için sorguyu yeniden çalıştırdığınızı varsayalım), FragmentStatePagerAdapter kullanmanız gerekir.

Burada bütün mesele, Parçacık sayısının ve benzer olup olmadıklarının her zaman göz önünde bulundurulması gereken kilit unsur olmadığıdır. Parçalarınızın dinamik olup olmadığı da önemlidir.


Diyelim ki A parçasında 2 parça, 1 geri dönüşüm görüntüsü var, bir öğeye tıkladığımda B parçasının içeriğini değiştiriyor, fragB.setText ("blablabla") yapıyorum. Durum çağrı cihazını kullanmalıyım?
Ced

Emin değilim ama evet derdim. Her ikisini de deneyin, yine de kodunuzu birinden diğerine değiştirmek gerçekten kolay ve hızlıdır.
JDenais

@JDenais Bunun doğru olduğundan emin misiniz? Ben kullanıyorum FragmentPagerAdapterher parçası listesini içerir - iki fragman göstermek için bir ViewPager kullanır benim aktivitesinde. İlk listem "Tüm Raporlar", ikinci listem "Favori Raporlar". İlk listede, bir raporun yıldız simgesine dokunursam, o raporun sık kullanılan durumunu değiştirmek için veritabanını günceller. Daha sonra hızlıca kaydırırım ve bu raporu ikinci listenin kullanıcı arayüzünde başarıyla görüyorum. Belki de örnekler hafızada tutulur, ancak bazı durumlarda (örneğin benimki) içerik aslında FragmentPagerAdapter için iyi güncellenir
ban-geoengineering

14

FragmentPagerAdapterbağdaştırıcıdan getirilen önceki verileri saklarken, FragmentStatePagerAdapterher yürütüldüğünde yeni değeri bağdaştırıcıdan alır.


4

FragmentStatePagerAdapter = Çok sayıda parçayı ViewPager'e yerleştirmek için. Bu bağdaştırıcı parçayı kullanıcı tarafından görülmediği zaman yok ettiğinden ve parçanın yalnızca saveInstanceState öğesi daha fazla kullanım için saklanır. Bu şekilde düşük miktarda bellek kullanılır ve dinamik fragmanlarda daha iyi bir performans sağlanır.


1

FragmentPagerAdapter : görünüm yok edilecek olsa da, kullanıcının ziyaret ettiği her sayfanın parçası bellekte saklanır. Dolayısıyla, sayfa tekrar görünür olduğunda görünüm yeniden oluşturulur, ancak parça örneği yeniden oluşturulmaz. Bu, önemli miktarda belleğin kullanılmasına neden olabilir. Tüm parçayı belleğe kaydetmemiz gerektiğinde FragmentPagerAdapter kullanılmalıdır. FragmentPagerAdapter işlemde kaldır (Fragment) yerine detach (Fragment) çağırır.

FragmentStatePagerAdapter : fragman örneği, parçanın kaydedilmiş durumu dışında Kullanıcı tarafından görülmediğinde yok edilir. Bu, yalnızca az miktarda Bellek kullanılmasına neden olur ve daha büyük veri kümelerinin işlenmesinde faydalı olabilir. Widget'lı fragmanlar gibi dinamik fragmanlar kullanmamız gerektiğinde kullanılmalıdır, çünkü verileri savedInstanceState'e kaydedilebilir.Ayrıca çok sayıda fragman olsa bile performansı etkilemez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.