Android Fundamentals-4 | ViewModel

Suveybesena
4 min readMay 3, 2022

--

Merhabalar,

Bu seride doküman okuma alışkanlığımı geliştirmek ve Android temellerine dair daha kapsamlı bilgi edinmek adına developer.android.com üzerinden seçtiğim konular hakkında notlarımı paylaşıyor olacağım. Keyifli okumalar:)

Android Jetpack’in bir parçası olan ViewModel sınıfı, UI ile ilgili verileri “lifecycle conscious” ( yaşam döngülerine duyarlı) bir şekilde depolamak ve yönetmek için tasarlanmıştır. ViewModel sınıfı, verilerin ekran döndürme gibi konfigurasyon değişikliklerinden kurtulmasını sağlar.

Android framework, activity ve fragmentlar gibi UI controller’ların yaşam döngülerini yönetir. Framework, tamamen kontrolümüz dışında olan belirli kullanıcı eylemlerine veya cihaz olaylarına yanıt olarak bir UI controller’ı yok etmeye veya yeniden oluşturmaya karar verebilir.

Sistem bir UI controller’ı yok ederse veya yeniden oluşturursa, içinde sakladığımız UI ile ilgili tüm geçici veriler kaybolur. Örneğin, uygulamamız aktivitelerden birinde bir kullanıcı listesi içerebilir. Aktivite bir konfigurasyon değişikliği için yeniden oluşturulduğunda, yeni aktivitenin kullanıcı listesini yeniden getirmesi gerekir. Basit veriler için, aktivite onSaveInstanceState() yöntemini kullanabilir ve verilerini onCreate() içindeki paketten geri yükleyebilir, ancak bu yaklaşım, potansiyel olarak büyük miktarda veri için değil, yalnızca küçük miktarlardaki veriler için uygundur.

Diğer bir sorun da, UI controller’ların sık sık, geri dönmesi biraz zaman alabilen asenkron çağrılar yapması gerekmesidir. UI controller’ın bu çağrıları yönetmesi ve olası bellek sızıntılarını önlemek için yok edildikten sonra sistemin bunları temizlemesini sağlaması gerekir. Bu yönetim çok fazla bakım gerektirir ve nesnenin bir konfigurasyon değişikliği için yeniden oluşturulması durumunda, nesnenin önceden yapmış olduğu çağrıları yeniden yayınlaması gerekebileceğinden, bu bir kaynak israfıdır.

Activity ve fragmentlar gibi UI controller’lar, öncelikle UI verilerini görüntüleme, kullanıcı eylemlerine tepki verme veya izin istekleri gibi işletim sistemi iletişimini işleme amaçlıdır. UI controller’ların bir veritabanından veya ağdan veri yüklemekten de sorumlu olması zorunlu kılınmamalıdır. UI controller’lara aşırı sorumluluk atamak, işi diğer sınıflara devretmek yerine bir uygulamanın tüm çalışmalarını kendi başına halletmeye çalışan tek bir sınıf oluşmasına neden olabilir. Bu durum testi de çok daha zor hale getirir.

ViewModel’ı implement edelim

Architecture Components, UI için veri hazırlamaktan sorumlu UI controller için ViewModel sınıfını sunar. ViewModel nesneleri, tuttukları verilerin bir sonraki activity veya fragment örneği için hemen kullanılabilir olması için konfigurasyon değişiklikleri sırasında otomatik olarak korunur. Örneğin, uygulamamızda bir kullanıcı listesi görüntülememiz gerekiyorsa;

UI contoller’da bu şekilde observeleyebiliriz;

Aktivite yeniden oluşturulursa, ilk aktivite tarafından oluşturulan aynı MyViewModel örneğini alır. Sahip etkinliği bittiğinde framework, kaynakları temizleyebilmesi için ViewModel nesnelerinin onCleared() yöntemini çağırır.

Dikkat: Bir ViewModel, bir görünüme, bir lifecycle’a veya aktivite Context’ine referans olabilecek herhangi bir sınıfa asla referans vermemelidir.

ViewModel nesneleri, görünümlerden veya LifecycleOwners’ın belirli örneklemelerinden daha uzun yaşaması için tasarlanmıştır. Bu tasarım aynı zamanda view ve lifecycle nesneleri hakkında bilgi sahibi olmadığı için bir ViewModel’i daha kolay kapsayacak testler yazabileceğimiz anlamına gelir. ViewModel nesneleri, LiveData nesneleri gibi LifecycleObservers içerebilir. Ancak ViewModel nesneleri, LiveData nesneleri gibi lifecycle-aware gözlemlenebilir öğelerdeki değişiklikleri hiçbir zaman gözlemlememelidir. ViewModel’in Application context ‘ine ihtiyacı varsa, AndroidViewModel sınıfını genişletebilir ve Application sınıfı Context’i extend ettiğinden, constructor’ında Application alan bir constructor’a sahip olabilir.

ViewModel nesneleri, ViewModel alınırken ViewModelProvider’a iletilen lifecycle’ın kapsamına alınır. ViewModel, kapsamı belirlenen lifecycle kalıcı olarak kaybolana kadar bellekte kalır: bir aktivite için aktivite tamamen bittiğinde , bir fragment için ise fragment detach() olduğunda sonlanır.

Sistem bir aktivite nesnesinin onCreate() yöntemini ilk çağırdığında genellikle ViewModel ‘ı burada yazarız. Sistem, bir cihaz ekranı döndürüldüğünde olduğu gibi, bir aktivitenin ömrü boyunca birkaç kez onCreate() öğesini çağırabilir. ViewModel, bir ViewModel’i ilk çağırdığımız andan aktivite tamamlanıp yok edilene kadar mevcuttur.

Fragmentlar arasında veri paylaşımı

Bir aktivitedeki iki veya daha fazla fragment birbiriyle iletişim kurabilir. Kullanıcının bir listeden bir öğe seçtiği bir fragmenta ve, seçilen öğenin içeriğini görüntüleyen başka bir fragmenta sahip olduğumuz bir durumu düşünelim. Bu durumda her iki fragment’ın da görünümleri tanımlamaları gerekir ve parent activity’nin ikisini birbirine bağlaması gerekir. Ayrıca her iki fragment da diğer fragment’ın henüz oluşturulmadığı ya da görünür olmadığı senaryoyu ele almalıdır.

Bu durum, ViewModel nesneleri kullanılarak çözülebilir. Bu fragment’lar, aşağıdaki örnek kodda gösterildiği gibi, bu iletişimi işlemek için activity scope kullanarak bir ViewModel’i paylaşabilir:

Bu yaklaşım aşağıdaki faydaları sağlar:

· Aktivitenin herhangi bir şey yapmasına veya bu iletişim hakkında hiçbir şey bilmesine gerek yoktur.

· Fragment’ların SharedViewModel dışında birbirleri hakkında bilgi sahibi olmaları gerekmez. Fragment’lardan biri kaybolursa diğeri her zamanki gibi çalışmaya devam eder.

· Her fragment’ın kendi yaşam döngüsü vardır ve diğerinin yaşam döngüsünden etkilenmez. Bir fragment diğerinin yerini alırsa, kullanıcı arayüzü sorunsuz çalışmaya devam eder.

Loader’ları ViewModel ile Değiştirme

CursorLoader gibi yükleyici sınıfları, bir uygulamanın UI verilerini bir veritabanıyla senkronize halde tutmak için sıklıkla kullanılır. Yükleyiciyi değiştirmek için ViewModel’i birkaç başka sınıfla birlikte kullanabilirsiniz. Bir ViewModel kullanmak, UI controlleri veri yükleme işleminden ayırır, bu da sınıflar arasındaki bağların daha gevşek olmasını sağlar.

ViewModel, yükleyiciyi değiştirmek için Room ve LiveData ile birlikte çalışır. ViewModel, verilerin bir konfigurasyon değişikliğinde hayatta kalmasını sağlar. Room, veritabanı değiştiğinde LiveData’nızı bilgilendirir ve LiveData sırayla kullanıcı arayüzünüzü revize edilmiş verilerle günceller.

Serinin devamı için;

Okuduğunuz için teşekkür ederim, bir sonraki yazıda görüşmek üzere :)

Referanslar ;
https://developer.android.com/topic/libraries/architecture/viewmodel

--

--