Dostrzegalność to zdolność obiektu do powiadamiania innych osób o zmianach w jego danych. Biblioteka powiązań danych umożliwia obserwację obiektów, pól i kolekcji.
Do powiązania danych możesz użyć dowolnego obiektu, ale modyfikacja obiektu nie spowoduje automatycznej aktualizacji interfejsu użytkownika. Dzięki wiązaniom danych obiekty danych mogą powiadamiać inne obiekty (tzw. detektory) o zmianie danych. Istnieją 3 typy klas możliwych do obserwacji: pola, kolekcje i obiekty.
Gdy jeden z tych możliwych do obserwacji obiektów danych jest powiązany z interfejsem użytkownika, a jego właściwość zmieni się, interfejs aktualizuje się automatycznie.
Obserwowalne pola
Jeśli klasy mają tylko kilka właściwości, utworzenie klas, które implementują interfejs Observable
, może być nieopłacalne. W takim przypadku możesz użyć ogólnej klasy Observable
i poniższych klas specyficznych dla obiektów podstawowych, aby umożliwić obserwację pól:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
Pola obserwowane to niezależne obserwowalne obiekty, które mają jedno pole. Wersje podstawowe zapobiegają pakowaniu i rozpakowywaniu podczas operacji dostępu. Aby użyć tego mechanizmu, utwórz właściwość public final
w języku programowania Java lub właściwość tylko do odczytu w Kotlin, jak pokazano w poniższym przykładzie:
Kotlin
class User { val firstName = ObservableField<String>() val lastName = ObservableField<String>() val age = ObservableInt() }
Java
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); }
Aby uzyskać dostęp do wartości pola, użyj metod akcesora set()
i get()
lub użyj składni właściwości Kotlin:
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Obserwowalne kolekcje
Niektóre aplikacje przechowują dane za pomocą dynamicznych struktur. Dostrzegalne zbiory
umożliwiają dostęp do tych struktur za pomocą klucza. Klasa ObservableArrayMap
jest przydatna, gdy klucz jest typem odwołania, takim jak String
, jak w tym przykładzie:
Kotlin
ObservableArrayMap<String, Any>().apply { put("firstName", "Google") put("lastName", "Inc.") put("age", 17) }
Java
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName", "Google"); user.put("lastName", "Inc."); user.put("age", 17);
Mapę możesz znaleźć w układzie za pomocą klawiszy ciągu znaków, jak w tym przykładzie:
<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"/>
Klasa ObservableArrayList
jest przydatna, gdy klucz jest liczbą całkowitą:
Kotlin
ObservableArrayList<Any>().apply { add("Google") add("Inc.") add(17) }
Java
ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google"); user.add("Inc."); user.add(17);
W układzie listy dostęp do listy możesz uzyskać przez indeksy, jak w tym przykładzie:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
android:text='@{user[Fields.LAST_NAME]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Obserwowalne obiekty
Klasa implementująca interfejs Observable
umożliwia rejestrowanie detektorów, którzy chcą otrzymywać powiadomienia o zmianach właściwości obiektu obserwowalnego.
Interfejs Observable
ma mechanizm dodawania i usuwania odbiorników, ale to Ty decydujesz, kiedy powiadomienia mają być wysyłane. Aby ułatwić programowanie, biblioteka wiązań danych udostępnia klasę BaseObservable
, która implementuje mechanizm rejestracji detektora. Klasa danych, która implementuje BaseObservable
, jest odpowiedzialna za powiadamianie o zmianach właściwości. Aby to zrobić, przypisz do metody pobierania adnotację Bindable
i wywołaj metodę notifyPropertyChanged()
w metodzie ustawiającej, jak w tym przykładzie:
Kotlin
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) } }
Java
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } }
Powiązanie danych powoduje wygenerowanie w pakiecie modułu klasy o nazwie BR
, która zawiera identyfikatory zasobów używanych do wiązania danych. Adnotacja Bindable
generuje wpis w pliku klasy BR
podczas kompilacji. Jeśli nie można zmienić klasy podstawowej na potrzeby klas danych, możesz wdrożyć interfejs Observable
za pomocą obiektu PropertyChangeRegistry
, aby skutecznie rejestrować i powiadamiać detektory.
Obiekty rozpoznające cykl życia
Układy w aplikacji mogą też być powiązane ze źródłami powiązań danych, które automatycznie powiadamiają interfejs użytkownika o zmianach w danych. Dzięki temu powiązania są uwzględniane w cyklu życia i aktywowane tylko wtedy, gdy interfejs użytkownika jest widoczny na ekranie.
Powiązanie danych obsługuje StateFlow
i LiveData
. Więcej informacji o korzystaniu z funkcji LiveData
do wiązania danych znajdziesz w artykule Używanie LiveData do powiadamiania interfejsu użytkownika o zmianach danych.
Użyj StateFlow
Jeśli Twoja aplikacja używa Kotlin w połączeniu z korutynami, jako źródła wiązań danych możesz używać obiektów StateFlow
. Aby użyć obiektu StateFlow
z klasą wiązania, określ właściciela cyklu życia w celu określenia zakresu obiektu StateFlow
. Ten przykład określa aktywność jako właściciela cyklu życia po utworzeniu wystąpienia klasy powiązania:
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
}
}
Jak opisano w sekcji Powiąż widoki układu z komponentami architektury, wiązanie danych działa bezproblemowo z obiektami ViewModel
. Aplikacji StateFlow
i ViewModel
można używać jednocześnie w następujący sposób:
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
W swoim układzie przypisz właściwości i metody obiektu ViewModel
do odpowiednich widoków, używając wyrażeń powiązań, jak pokazano w tym przykładzie:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
Interfejs jest automatycznie aktualizowany po każdej zmianie wartości nazwy użytkownika.
Wyłącz obsługę StateFlow
W przypadku aplikacji korzystających z Kotlin i AndroidaX obsługa StateFlow
jest automatycznie dodawana wraz z powiązaniem danych. Oznacza to, że zależność od współuczestników jest automatycznie dodawana do aplikacji, jeśli nie jest jeszcze dostępna.
Możesz zrezygnować z tej funkcji, dodając do pliku build.gradle
ten fragment:
Odlotowy
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
Możesz też wyłączyć usługę StateFlow
globalnie w projekcie, dodając ten wiersz do pliku gradle.properties
:
Odlotowy
android.defaults.databinding.addKtx = false
Kotlin
android.defaults.databinding.addKtx = false
Dodatkowe materiały
Więcej informacji o wiązaniach danych znajdziesz w tych artykułach:
Próbki
Ćwiczenia z programowania
Posty na blogu
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Moduł zapisanego stanu dla modelu ViewModel
- Powiązanie widoków układu z komponentami architektury
- Omówienie biblioteki stronicowania