ViewModel'e genel bakış Android Jetpack'in bir parçasıdır.
ViewModel
sınıfı, bir işletme mantığı veya ekran düzeyinde durum sahibidir. Durumu kullanıcı arayüzüne gösterir ve ilgili iş mantığını kapsar.
En önemli avantajı durumu önbelleğe alması ve yapılandırma değişiklikleri boyunca sürdürebilmesidir. Böylece, etkinlikler arasında gezinirken veya ekranı döndürme gibi yapılandırma değişikliklerini takip ederken kullanıcı arayüzünüzün verileri tekrar getirmesi gerekmez.
Devlet sahipleri hakkında daha fazla bilgi için eyalet sahiplerinin rehberini inceleyin. Benzer şekilde, genel olarak kullanıcı arayüzü katmanı hakkında daha fazla bilgi edinmek için kullanıcı arayüzü katmanı kılavuzuna bakın.
ViewModel'in avantajları
ViewModel'in alternatifi, kullanıcı arayüzünüzde görüntülediğiniz verileri tutan düz bir sınıftır. Bu durum, etkinlikler arasında gezinirken veya Navigasyon hedefleri arasında gezinirken sorun oluşturabilir. Bu işlem, örnek durum mekanizmasını kullanarak depolamazsanız verileri yok eder. ViewModel, veri kalıcılığı için bu sorunu çözen kullanışlı bir API sunar.
ViewModel sınıfının temel avantajları şunlardır:
- Kullanıcı arayüzü durumunu korumanızı sağlar.
- İş mantığına erişim sağlar.
Kalıcı
ViewModel, hem bir ViewModel'in sahip olduğu durum hem de bir ViewModel'in tetiklediği işlemler aracılığıyla kalıcılığa izin verir. Bu önbelleğe alma, ekran rotasyonu gibi yaygın yapılandırma değişiklikleri üzerinden verileri tekrar getirmenize gerek olmadığı anlamına gelir.
Kapsam
Bir ViewModel'i örneklediğinizde, buna ViewModelStoreOwner
arayüzünü uygulayan bir nesne geçirirsiniz. Bu, bir Gezinme hedefi, Gezinme grafiği, etkinlik, parça veya arayüzü uygulayan başka herhangi bir tür olabilir. ViewModel'iniz daha sonra ViewModelStoreOwner
Yaşam Döngüsü kapsamına alınır. ViewModelStoreOwner
kalıcı olarak ortadan kalkana kadar bellekte kalır.
Sınıf aralığı, ViewModelStoreOwner
arayüzünün doğrudan veya dolaylı alt sınıflarıdır. Doğrudan alt sınıflar: ComponentActivity
, Fragment
ve NavBackStackEntry
.
Dolaylı alt sınıfların tam listesi için ViewModelStoreOwner
referansına bakın.
ViewModel'in kapsamındaki parça veya etkinlik kaldırıldığında, eşzamansız çalışma, kapsama alınan ViewModel'de devam eder. Kalıcılığın anahtarı budur.
Daha fazla bilgi için aşağıdaki ViewModel yaşam döngüsü bölümüne bakın.
SavedStateHandleez
SavedStateHandle, verileri yalnızca yapılandırma değişiklikleriyle değil, aynı zamanda işlem yeniden oluşturma süreciyle de tutmanıza olanak tanır. Yani, kullanıcı uygulamayı kapatıp daha sonra açtığında bile kullanıcı arayüzü durumunu olduğu gibi korumanızı sağlar.
İş mantığına erişim
İş mantığının büyük çoğunluğu veri katmanında mevcut olsa da kullanıcı arayüzü katmanı, iş mantığını da içerebilir. Ekran kullanıcı arayüzü durumunu oluşturmak için birden fazla depodan veri birleştirirken veya belirli bir veri türü veri katmanı gerektirmediğinde bu durum geçerli olabilir.
ViewModel, kullanıcı arayüzü katmanında iş mantığını işlemek için doğru yerdir. ViewModel, etkinlikleri işlemek ve uygulama verilerini değiştirmek için iş mantığının uygulanması gerektiğinde bu etkinlikleri hiyerarşinin diğer katmanlarına yetkilendirmekten de sorumludur.
Jetpack Compose
Jetpack Compose'u kullanırken ViewModel'i kullanarak ekran kullanıcı arayüzü durumlarını composable'lara gösterebilirsiniz. Karma uygulamalarda, etkinlikler ve parçalar composable işlevlerinizi barındırır. Bu, etkinlikler ve parçalarla yeniden kullanılabilir kullanıcı arayüzü parçaları oluşturmanın basit ve sezgisel olmadığı geçmiş yaklaşımlardan uzaklaşıp kullanıcı arayüzü denetleyicileri olarak çok daha aktif olmalarını sağlayan bir geçiş.
ViewModel'i Compose ile kullanırken unutulmaması gereken en önemli şey, ViewModel'i bir composable'a ayarlayamayacağınızdır. Bunun nedeni, composable'ın
ViewModelStoreOwner
olmamasıdır. Beste içindeki aynı composable'ın iki örneği veya aynı ViewModel türüne erişen iki farklı composable, aynı ViewModelStoreOwner
altında ViewModel'in aynı örneğini alır. Bu, genellikle beklenen davranış değildir.
Compose'da ViewModel'in avantajlarından yararlanmak için her ekranı bir Parça veya Etkinlikte barındırın ya da Oluşturma Gezinme özelliğini kullanın ve ViewModel öğelerini Gezinme hedefine mümkün olduğunca yakın composable işlevlerde kullanın. Çünkü bir ViewModel’i Gezinme hedeflerine, Gezinme grafiklerine, Etkinliklere ve Parçalara kapsama alabilirsiniz.
Daha fazla bilgi için Jetpack Compose'da eyalet yükseltme rehberini inceleyin.
ViewModel uygulama
Aşağıda, kullanıcının zar atmasına izin veren bir ekran için ViewModel'in uygulanmasına bir örnek verilmiştir.
Kotlin
data class DiceUiState(
val firstDieValue: Int? = null,
val secondDieValue: Int? = null,
val numberOfRolls: Int = 0,
)
class DiceRollViewModel : ViewModel() {
// Expose screen UI state
private val _uiState = MutableStateFlow(DiceUiState())
val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()
// Handle business logic
fun rollDice() {
_uiState.update { currentState ->
currentState.copy(
firstDieValue = Random.nextInt(from = 1, until = 7),
secondDieValue = Random.nextInt(from = 1, until = 7),
numberOfRolls = currentState.numberOfRolls + 1,
)
}
}
}
Java
public class DiceUiState {
private final Integer firstDieValue;
private final Integer secondDieValue;
private final int numberOfRolls;
// ...
}
public class DiceRollViewModel extends ViewModel {
private final MutableLiveData<DiceUiState> uiState =
new MutableLiveData(new DiceUiState(null, null, 0));
public LiveData<DiceUiState> getUiState() {
return uiState;
}
public void rollDice() {
Random random = new Random();
uiState.setValue(
new DiceUiState(
random.nextInt(7) + 1,
random.nextInt(7) + 1,
uiState.getValue().getNumberOfRolls() + 1
)
);
}
}
Daha sonra, ViewModel'e bir etkinlikten şu şekilde erişebilirsiniz:
Kotlin
import androidx.activity.viewModels
class DiceRollActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same DiceRollViewModel instance created by the first activity.
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
val viewModel: DiceRollViewModel by viewModels()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Update UI elements
}
}
}
}
}
Java
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
model.getUiState().observe(this, uiState -> {
// update UI
});
}
}
Jetpack Compose
import androidx.lifecycle.viewmodel.compose.viewModel
// Use the 'viewModel()' function from the lifecycle-viewmodel-compose artifact
@Composable
fun DiceRollScreen(
viewModel: DiceRollViewModel = viewModel()
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
// Update UI elements
}
ViewModel ile eş yordamlar kullanma
ViewModel
, Kotlin eş yordamlarını destekler. Sistem, kullanıcı arayüzü durumunu koruduğu gibi eşzamansız çalışmayı da devam ettirebilir.
Daha fazla bilgi için Android Mimari Bileşenleri ile Kotlin eş yordamlarını kullanma bölümüne bakın.
Bir ViewModel'in yaşam döngüsü
Bir ViewModel
'ın yaşam döngüsü doğrudan kapsamına bağlıdır. Bir ViewModel
, kapsama dahil edildiği ViewModelStoreOwner
kaybolana kadar bellekte kalır. Bu durum, aşağıdaki bağlamlarda gerçekleşebilir:
- Bir etkinlik olduğunda, etkinlik bittiğinde.
- Ayrılan parça olması durumunda.
- Bir Navigasyon girişi olması durumunda, giriş arka yığından kaldırıldığında.
Bu nedenle ViewModels, yapılandırma değişikliklerinden sonra dayanabilen verileri depolamak için mükemmel bir çözümdür.
Şekil 1'de bir aktivite rotasyona girip ardından biterken oluşan çeşitli yaşam döngüsü durumları gösterilmektedir. Bu görselde, ilişkili etkinlik yaşam döngüsünün yanında ViewModel
ömrü de gösterilmektedir. Bu şemada, bir etkinliğin durumu gösterilmektedir. Bir parçanın yaşam döngüsü için de aynı temel durumlar geçerlidir.
Sistem bir etkinlik nesnesinin onCreate()
yöntemini ilk kez çağırdığında genellikle bir ViewModel
isteğinde bulunursunuz. Sistem, cihaz ekranı döndürüldüğünde olduğu gibi bir etkinliğin varlığı boyunca onCreate()
'i birkaç kez çağırabilir. ViewModel
, ViewModel
için ilk istekte bulunmanızdan etkinlik bitip silinene kadar devam eder.
ViewModel bağımlılıklarını temizleme
ViewModelStoreOwner
, yaşam döngüsü içinde modeli yok ettiğinde ViewModel onCleared
yöntemini çağırır. Bu, ViewModel'in yaşam döngüsünü takip eden işleri veya bağımlılıkları temizlemenize olanak tanır.
Aşağıdaki örnekte viewModelScope
'in bir alternatifi gösterilmektedir.
viewModelScope
, ViewModel'in yaşam döngüsünü otomatik olarak takip eden yerleşik bir CoroutineScope
'dir. ViewModel, işle ilgili işlemleri tetiklemek için bu modeli kullanır. Daha kolay test yapmak için viewModelScope
yerine özel bir kapsam kullanmak isterseniz ViewModel, oluşturucusuna bağımlılık olarak bir CoroutineScope
alabilir. ViewModelStoreOwner
, yaşam döngüsünün sonunda ViewModel'i temizlediğinde, ViewModel CoroutineScope
öğesini de iptal eder.
class MyViewModel(
private val coroutineScope: CoroutineScope =
CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
) : ViewModel() {
// Other ViewModel logic ...
override fun onCleared() {
coroutineScope.cancel()
}
}
Yaşam döngüsü 2.5 ve sonraki sürümlerinden, ViewModel örneği temizlendiğinde otomatik olarak kapanan ViewModel oluşturucuya bir veya daha fazla Closeable
nesnesi geçirebilirsiniz.
class CloseableCoroutineScope(
context: CoroutineContext = SupervisorJob() + Dispatchers.Main.immediate
) : Closeable, CoroutineScope {
override val coroutineContext: CoroutineContext = context
override fun close() {
coroutineContext.cancel()
}
}
class MyViewModel(
private val coroutineScope: CoroutineScope = CloseableCoroutineScope()
) : ViewModel(coroutineScope) {
// Other ViewModel logic ...
}
En iyi uygulamalar
ViewModel'i uygularken izlemeniz gereken birkaç önemli en iyi uygulama aşağıda verilmiştir:
- Kapsamları nedeniyle ViewModel'leri, ekran düzeyinde durum sahibinin uygulama ayrıntıları olarak kullanın. Bunları, çip grupları veya formlar gibi yeniden kullanılabilir kullanıcı arayüzü bileşenlerinin durum sahipleri olarak kullanmayın. Aksi takdirde, aynı ViewModel örneğini aynı ViewModelStoreOwner altında aynı kullanıcı arayüzü bileşeninin farklı kullanımlarında alırsınız.
- ViewModels, kullanıcı arayüzü uygulama ayrıntıları hakkında bilgi sahibi olmamalıdır. ViewModel API'nin sunduğu yöntemlerin ve kullanıcı arayüzü durumu alanlarının adlarını mümkün olduğunca genel bir şekilde belirtin. Bu sayede ViewModel'iniz cep telefonu, katlanabilir cihaz, tablet ve hatta Chromebook olmak üzere her tür kullanıcı arayüzünü barındırabilir.
- ViewModel'ler,
ViewModelStoreOwner
'dan daha uzun süre dayanabileceğinden bellek sızıntılarını önlemek içinContext
veyaResources
gibi yaşam döngüsüyle ilgili API'lere referans vermemelidir. - ViewModel'leri diğer sınıflara, işlevlere veya diğer kullanıcı arayüzü bileşenlerine geçirmeyin. Platform bunları yönettiğinden kullanıcıları mümkün olduğunca yakın tutmalısınız. Etkinlik, parça veya ekran düzeyinde composable işlevinizin yakınında. Bu, alt düzey bileşenlerin ihtiyaç duyduklarından daha fazla veriye ve mantığa erişmesini önler.
Daha fazla bilgi
Verileriniz daha karmaşık hale geldikçe, verileri yüklemek için ayrı bir sınıf oluşturmayı tercih edebilirsiniz. ViewModel
'in amacı, verilerin yapılandırma değişikliklerinden sonra da dayanmasını sağlamak için bir kullanıcı arayüzü denetleyicisine ait verileri kapsüllemektir. Yapılandırma değişikliklerindeki verileri yükleme, saklama ve yönetme hakkında bilgi edinmek için Kayıtlı Kullanıcı Arayüzü Durumları'na göz atın.
Android Uygulama Mimarisi Kılavuzu'nda, bu işlevleri işlemek için bir depo sınıfı derleyebilirsiniz.
Ek kaynaklar
ViewModel
sınıfı hakkında daha fazla bilgi için aşağıdaki kaynaklara başvurun.
Dokümanlar
- Kullanıcı arayüzü katmanı
- Kullanıcı Arayüzü Etkinlikleri
- Eyalet sahipleri ve kullanıcı arayüzü durumu
- Durum üretimi
- Veri katmanı
Numuneler
Sizin için önerilenler
- Not: Bağlantı metni JavaScript kapalıyken görüntülenir
- Yaşam döngüsüne duyarlı bileşenlerle Kotlin eş yordamlarını kullanma
- Kullanıcı arayüzü durumlarını kaydetme
- Sayfalandırılmış verileri yükleme ve görüntüleme