Android Fragment Caching

Gürkan Kesgin
KoçSistem
Published in
2 min readAug 13, 2018

Uygulamanızda birden çok fragment olduğunu ve aynı fragment’ları tekrar tekrar kullandığınızı varsayalım. Yapmak istediğimiz; kullanılan fragment’ları cache’lemek ve tekrar oluşturma maaliyetinden kurtulmaktır. Aynı zamanda önbellek yönetimiyle efor harcamak istemiyoruz. Bunun için Fragment API’da bulunan hali hazırda bir sınıf var: FragmentManager.

NEDEN

Örnek olarak; Instagram uygulamasında 5 tane tab var ve aslında her bir sayfa bizim için fragment nesnesi. Bu fragment’lar scroll edildiğinde, aynı data ve aynı pozisyonda kaldıkları yerden devam ederler(state tutulur). Bu yazıda, data kaybına uğramadan ve UI’da son kaldığı yerden devam edebildiği çözümü paylaşacağım.

NASIL ?

1.Adım

add methodunu kullanarak sürekli container view’a yeni fragment eklemiş olursunuz. Yani ne data’yı ne de UI state’i korumuş oluruz. Bunun yerine ise; yapmamız gereken replace metodunu kullanmak olmalıdır. Bu işlem için aşağıdaki örneği inceleyebilirsiniz.

FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frStack = manager.findFragmentByTag("Tag");


if (frStack == null) {
transaction.replace(R.id.main_fl, frNew, "Tag");
} else {
transaction.replace(R.id.main_fl, frStack);
}
transaction.addToBackStack(null);
transaction.commit();

Yukarıdaki kod bloğunda; yeni oluşturulacak olan fragment stack’te var mı (findFragmentByTag)?, kontrolü gerçekleştirilir. Eğer yoksa, yeni fragment’ı eklenir, varsa eski mevcutta oluşturulmuş olan fragmentı kullanılır.

2.Adım

Ama replace ile çağırdığımızda da göreceksiniz ki oncreateview, onresume … metodları tekrar çalışmış olacak(bakınız: fragment lyfecycle ). Yapılması gereken ise; oncreateview veya onresume metodunda çağrılan fonksiyonları çağırmadan yanlızca rootview’i return etmek.

private View view;
private boolean isLoaded;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup cntr,Bundle savedInstanceState) {

if (isLoaded == false) {
view = inflater.inflate(R.layout.fragment_scroll, cntr);
...
service call, findbyViewIds ...
...
isLoaded = true;
}

return view;
}

2.adımı farklı yöntemlerle de yapabilirsiniz! Burada amaç, fragment ilk oluşturulduğunda yapılan operasyonların; servis çağrısı, setonclick ve benzeri işlemlerin replace’de yapılmamasıdır.

SONUÇ

Aşağıdaki görsel üzerinden tüm fragmentların durumlarını(state) koruduğunu görebilirisniz. Örnek projeyi inceleyebilirsiniz.

NOT 1

Burada show(), -hide() yöntemi de uygulanabilir, caching neden gerekli diyebilirsiniz. Ama bu yöntem tüm fragmentlarınızı ayakta tutar, yani hepsi aslında onresume da kalır. Replace ettiğinizde ise, fragment’lar sırasıyla pause, stop metodlarından geçerek container’dan fragment’ı sökmüş olursunuz. Replace etmek “hide, show ” yöntemine göre daha maaliyetli olmasına karşın, memory’den kazandırma gibi önemli bir kozu var. Hide yaptıktan sonra ayakta kalan tüm fragment’larınızın memory’de kaldığını ve “out of memory” hatası alabileceğinizi göz önünde bulundurmalısınız.

NOT 2

transaction.addToBackStack(null);

addtobackstack metodu yaptığımız replace işleminin stack’te bir karşılığı olduğunu belirtiyor. Aksi halde tab’lar arası geçişte cache’ten hiç bir şey gelmediğini ve geri butonunda tüm fragment’larınızın tek seferde kaybolduğunu göreceksiniz.

--

--