Jetpack Compose : State Kavramı

Süleyman Sezer
HardwareAndro
Published in
4 min readApr 9, 2021

Herkese selamlar. Bu yazımda sizlere Compose içerisinde önemli bir yere sahip olan state kavramından bahsedeceğim.

State bir durumdur. Ekrana çizdirilmiş view ögelerinin o anki durumunu saklamamıza yardımcı olur. Bu sayede eğer bir view ögesinin sakladığı state değişirse, bu statenin etkilediği diğer view ögeleri de yeniden çizdirilir.

Composable fonksiyonlar remember ile işaretlenmiş objeleri hafızada saklayabilirler. Bu sayede objenin içeriği değiştiği zaman o objeyi işaret eden tüm viewlar recompositiona(yeniden çizdirilme) uğramış olur.

Ayrıca remember ile işaretlenmiş bir nesnenin içeriğine initial adımında kullanılabilir bir değer verilebilir. rememberSaveable kullanarakta aynı bundle nesnesinde olduğu gibi nesneler lifecycle için saklanır hale getirilir.(onpause→onresume)

remember ile hatırlanacak değerler 3 farklı şekilde saklanabilir.

  • val mutableState = remember { mutableStateOf(default) }
  • val value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }

Örneğin şöyle basit bir textField’ımız olsun ve değer değiştiği zaman text içeriği de değişsin.

remember yardımıyla değişkenlerin durumlarını(state) dahili bellekte saklayabiliriz. Bu sayede text bir değişikliğe uğradığında durumu değişecek ve bu textin kullanıldığı her view ögesi üzerinde de yeniden çizdirilme işlemi yapılacaktır. Google dokümanında önerildiği üzere Composable fonksiyonlarda kullanılan ve değeri değişebilen tüm değişkenler gözlemlenebilir olmalıdır. Gözlemlenebilirden kasıt view ögesinin kendi başına tekrar çizdirilmesidir. Bizim amacımız tekrar setText gibi metotları kullanmak yerine ögenin kendi kendine çizdirilme işlevini gerçekleştirmesine imkan sağlamaktır.

Not : Android Studio Arctic Fox | 2020.3.1 | Canary 8 sürümünde remember ile objeyi işaretlerken kütüphane import edilmesinde hata alınıyor. Bunun için şu kütüphaneyi elle import etmemiz gerekiyor.

import androidx.compose.runtime.*

Stateler, Composble fonksiyon içerisindeki olaylarda değişmelidir. ArrayList veya verileri değişebilen bir sınıf gözlemlenemez( data classlar ve final olmayan tipler). Verileri gözlemlenemediği için de compose tarafından içlerindeki veri değişse bile uide bir değişiklik olmaz.Bunun yerine State<List<T>> tarzında veya listOf() gibi değişken ekleme çıkartma yapılamayan data setleri kullanılmalıdır.

State kullanımında iki farklı kontrol durumu ortaya çıkıyor. Bu durumlar:

  • Statefull Kullanım
  • Stateless Kullanım

Statefull Kullanım : View içerisindeki statenin kendi kendine kontrolünü sağladığı kullanımdır. Durumu başka bir fonksiyona veya kullanıcı etkileşimine bağlı değildir. Kısaca kendi kendine işlemlerini yapabilmektedir. Aynı yukarıdaki text örneğinde olduğu gibi.

Stateless Kullanım : Statefull kullanımın tam tersi diyebiliriz. Yani view ögesinin durumu başka bir fonksiyonun durumuna bağlıdır. Bağlı olduğu başka bir view değiştiği zaman bu view ögeside recompositiona uğrar.

Yukarıda açıklanan state kullanımları viewların state yönetimlerini yapabilmek için çok önemli kavramlardır. Ayrıca State yönetimi yapabilmek için Google’nin de önerdiği State Hoisting adında bir Compose Pattern’i kullanmamız gerekiyor.

State Hoisting Nedir?

State hoisting, composable fonksiyonları tekrar kullanılabilir hale getirmek için kullanılan bir compose patternidir. Burada amaç composable fonksiyonları olabildiğinde sade hale getirmek, kod karmaşıklığını önlemek ve test edilebilir hale getirmektir. State hoisting kullanarak stateful olan compose fonksiyonunu stateless hale getiriyoruz. Yani kendi kararını kendi vermesini ortadan kaldırıyor ve bir fonksiyona bağlı hale getiriyoruz. Bu sayede bu compose fonksiyonunun kod karmaşısını ortadan kaldırıp tekrar kullanılabilir hale getiriyoruz.

State hoisting fonksiyonuna genelde bir view ögesinin o anki değerini(value) ve değer değişimini(on value change) gönderiyoruz.Hoisting içerisinde işlemleri yapıyor ve value değişirse view ögelerine recomposition yaptırıyoruz. Androiddeki MVP patterninin view kısmı gibi düşünebiliriz. Sadece viewda oluşan girdi,tıklama vs işlemlerini presentera yani hoistinge haber veriyoruz.

State hoistingin bize sağladığı faydalar:

  • Her bir compose fonksiyonunda kontrol sağlamaktansa tek bir yerden veriyi yönettiğimiz için kod karmaşasının önüne geçiyoruz. (Single Source Of Truth)
  • Farklı view ögeleri birbirleri ile etkileşim yapıyorsa bunları kolayca paylaşımlı hale getirebiliyoruz. Örneğin fab butonu basıldığında expandedcard expand durumuna geçecekse hoistingte bunu yapıp recomposing yapmasını sağlayabiliyoruz.(Shareable)
  • Sadece statefull compose fonksiyonunda veriler değişebiliyor. Veri güvenliği sağlanmış oluyor(Encapsulated)
  • Verileri viewModel içerisinde sağlayabilir ve viewModelin kullanıldığı her yerde verileri triggerlanabilir hale getiriyoruz.(DeCoupled)

Hoisting için 3 kural vardır.

  1. Eğer viewda okuma durumu varsa en düşük ortak ebeveyne yükseltilmelidir. ( okuma durumu → viewlara ögeleri set etme)
  2. Eğer viewda yazma durumu varsa en yüksek seviyeye yükseltilmelidir. ( yazma durumu → kullanıcının ui ile etkileşimi)
  3. Eğer 2 durum değişikliği aynı olayla değişebiliyorsa bunlar ortak bir hoistingte yer almalıdır.

Örneğin şöyle basit bir örnek ele alalım:

Yukarıda hem text hem de button viewları var. Burada butonun tıklama işlemi ve textin göstereceği value değerini başka bir fonksiyona bağımlı hale getirirdik. Yani statelerini bir üst fonksyiona vermiş olduk. Tıklama olduğunda hoisting fonksyionunda count değişkeni 1 artıyor ve count değişkenini state olarak tutan view ögeleri recompositiona uğramış oluyor. Yani normalde text ve buton ögeleri statefull kullanım içerirken bunları bir üst fonksiyona bağımlı hale getiriyoruz ve stateless durumuna getiriyoruz.

Bu sayede butonu ve texti tekrar kullanılabilir hale getirmiş oluyoruz. Zaten Jetpack Compose’nin çıkış amaçlarından birisi de tekrar kullanılabilir ui ögeleri oluşturmaktır.

--

--

Süleyman Sezer
HardwareAndro

Native Android Developer at Anadolu Hayat Emeklilik