Android — Observable Data Objeleri ile Çalışma
Gözlenebilirlik(Observability), bir nesnedeki değişiklikler hakkında diğerlerini bilgilendirmeyi sağlar. Data Binding kütüphanesi objeleri, fieldları ve collectionları gözlemlenebilir hale getirmeyi sağlar.
Data binding, veri nesnelerinize, verileri değiştiğinde listener olarak bilinen diğer nesneleri bildirme yeteneği vermek için kullanılabilir. Üç farklı türde gözlemlenebilir sınıf vardır: objeler, fieldlar ve collectionlar. Bu gözlemlenebilir veri nesnelerinden biri UI’a bağlandığında ve veri nesnesinin bir özelliği değiştiğinde, UI otomatik olarak güncellenir.
Observable fields
Eğer oluşturduğunuz sınıf sadece bir kaç özelliğe sahipse bu durumda özellikleri gözlemlenebilir hale getirmek için Observable Fields
kullanılabilir. Observable fields tek bir alana sahip gözlemlenebilir nesnelerdir. Bu mekanizmayı kullanmak için kotlinde sadece okunabilir(read-only) bir özellik oluşturulur:
class User {
val firstName = ObservableField<String>()
val lastName = ObservableField<String>()
val age = ObservableInt()
}
Field değerine erişmek için get()
ve set()
kullanılır.
user.firstName = "Google"
val age = user.age
Observable collections
Bazı uygulamalar, verileri tutmak için dinamik yapılar kullanır. Observable collectionlar, bir key kullanarak bu yapılara erişim sağlar. ObservableArrayMap
sınıfı, key, aşağıdaki örnekte gösterildiği gibi, String
gibi bir değer olduğunda kullanışlıdır:
ObservableArrayMap<String, Any>().apply {
put("firstName", "Google")
put("lastName", "Inc.")
put("age", 17)
}
Layout içerisinde, map keyler aracılığıyla kullanılabilir:
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{String.valueOf(1 + (Integer)user.age)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Observable objects
Observable interfaceini uygulayan bir sınıf, observable object üzerindeki özellik değişikliklerinden haberdar olmak isteyen listenerların kaydına izin verir.
Observable interfaceinde listener eklemek ve çıkarmak için bir mekanizma vardır. Geliştirmeyi kolaylaştırmak için Data Binding Library, listener kayıt mekanizmasını uygulayan BaseObservable
sınıfını sağlar. BaseObservable’ı uygulayan data sınıfı, özellikler değiştiğinde bildirmekten sorumludur. Bu, aşağıdaki örnekte gösterildiği gibi, Bindable getter kullanılarak ve </code>notifyPropertyChanged()</code> metodu set edilerek kullanılır.
class User : BaseObservable() {
@get:Bindable
var firstName: String = ""
set(value) {
field = value
notifyPropertyChanged(BR.firstName)
}
@get:Bindable
var lastName: String = ""
set(value) {
field = value
notifyPropertyChanged(BR.lastName)
}
}
Data binding, veri bağlama işlemi için BR adlı bir sınıf oluşturur. Bindable
anotasyonu, derleme sırasında BR sınıfı dosyasında bir giriş oluşturur. Data sınıfları için için base sınıf değiştirilemiyorsa, Observable
interface, bir PropertyChangeRegistry
nesnesi kullanılarak kaydedilmesi ve dinleyicilere verimli bir şekilde bildirilmesi için uygulanabilir.
Lifecycle-aware objects
Uygulamanızdaki layoutlar, verilerdeki değişiklikler hakkında UI’yi otomatik olarak bilgilendiren data binding kaynaklarına da bağlanabilir. Bu şekilde, bindingler yaşam döngüsüne duyarlıdır ve yalnızca UI ekranda göründüğünde tetiklenir. Data Binding şu anda StateFlow
ve LiveData
‘yı desteklemektedir.
StateFlow Kullanımı
Uygulamanız Kotlin coroutines kullanıyorsa, data binding kaynağı olarak StateFlow
nesnelerini kullanabilirsiniz. Bir StateFlow
nesnesini binding sınıfınızla kullanmak için StateFlow nesnesinin scopeunu tanımlamak üzere bir yaşam döngüsü sahibi belirtmeniz gerekir. Aşağıdaki örnek, binding sınıfı örneklendirildikten sonra activityi yaşam döngüsü sahibi olarak belirtir:
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Specify the current activity as the lifecycle owner.
binding.lifecycleOwner = this
}
}
Data Binding, ViewModel nesneleriyle sorunsuz bir şekilde çalışır. StateFlow
ve ViewModel
‘i aşağıdaki gibi birlikte kullanabilirsiniz:
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
Layout içerisinde aşağıdaki örnekte gösterildiği gibi, binding ifadelerini kullanarak ViewModel nesnenizin özelliklerini ve yöntemlerini karşılık gelen görünümlere atayın:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
Kullanıcı adı değeri değiştiğinde UI otomatik olarak güncellenir.