Khả năng quan sát là khả năng một đối tượng thông báo cho người khác về những thay đổi trong dữ liệu. Thư viện liên kết dữ liệu cho phép bạn quan sát các đối tượng, trường hoặc bộ sưu tập.
Bạn có thể sử dụng bất kỳ đối tượng nào để liên kết dữ liệu, nhưng việc sửa đổi đối tượng đó sẽ không tự động cập nhật giao diện người dùng. Bạn có thể sử dụng tính năng liên kết dữ liệu để cho phép các đối tượng dữ liệu thông báo cho các đối tượng khác (gọi là trình nghe) khi dữ liệu của các đối tượng đó thay đổi. Có 3 loại lớp có thể quan sát: trường, bộ sưu tập và đối tượng.
Khi một trong các đối tượng dữ liệu có thể quan sát này được liên kết với giao diện người dùng và một thuộc tính của đối tượng dữ liệu thay đổi, giao diện người dùng sẽ tự động cập nhật.
Các trường có thể quan sát
Nếu các lớp của bạn chỉ có một vài thuộc tính, thì có thể bạn không cần tạo các lớp triển khai giao diện Observable
. Trong trường hợp này, bạn có thể sử dụng lớp Observable
chung và các lớp cụ thể nguyên gốc sau đây để khiến các trường có thể quan sát được:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
Các trường có thể quan sát là các đối tượng có thể quan sát độc lập, có một trường duy nhất. Các phiên bản gốc tránh việc đóng hộp và mở hộp trong các thao tác truy cập. Để sử dụng cơ chế này, hãy tạo một thuộc tính public final
bằng ngôn ngữ lập trình Java hoặc thuộc tính chỉ có thể đọc trong Kotlin, như trong ví dụ sau:
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(); }
Để truy cập vào giá trị của trường, hãy dùng phương thức truy cập set()
và get()
hoặc sử dụng cú pháp thuộc tính Kotlin:
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Bộ sưu tập có thể quan sát
Một số ứng dụng dùng cấu trúc động để lưu giữ dữ liệu. Các bộ sưu tập có thể quan sát được cho phép truy cập vào các cấu trúc này bằng cách sử dụng một khoá. Lớp ObservableArrayMap
rất hữu ích khi khoá là loại tham chiếu, chẳng hạn như String
, như minh hoạ trong ví dụ sau:
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);
Trong bố cục, bạn có thể tìm thấy bản đồ bằng cách sử dụng các khoá chuỗi, như trong ví dụ sau:
<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"/>
Lớp ObservableArrayList
hữu ích khi khoá là một số nguyên, như sau:
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);
Trong bố cục, bạn có thể truy cập danh sách thông qua các chỉ mục, như trong ví dụ sau:
<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"/>
Vật thể quan sát được
Một lớp triển khai giao diện Observable
cho phép đăng ký các trình nghe muốn nhận thông báo về các thay đổi thuộc tính từ đối tượng có thể quan sát.
Giao diện Observable
có cơ chế để thêm và xoá trình nghe, nhưng bạn sẽ quyết định thời điểm gửi thông báo. Để giúp việc phát triển dễ dàng hơn, Thư viện liên kết dữ liệu cung cấp lớp BaseObservable
, lớp này triển khai cơ chế đăng ký trình nghe. Lớp dữ liệu triển khai BaseObservable
chịu trách nhiệm thông báo khi các thuộc tính thay đổi. Để làm điều này, hãy chỉ định một chú giải Bindable
cho phương thức getter và gọi phương thức notifyPropertyChanged()
trong phương thức setter, như trong ví dụ sau:
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); } }
Tính năng liên kết dữ liệu tạo ra một lớp có tên BR
trong gói mô-đun, lớp này chứa mã nhận dạng của các tài nguyên dùng để liên kết dữ liệu. Chú giải Bindable
tạo một mục nhập trong tệp lớp BR
trong quá trình biên dịch. Nếu không thể thay đổi lớp cơ sở cho các lớp dữ liệu, bạn có thể triển khai giao diện Observable
bằng cách sử dụng đối tượng PropertyChangeRegistry
để đăng ký và thông báo hiệu quả cho trình nghe.
Đối tượng nhận biết vòng đời
Các bố cục trong ứng dụng cũng có thể liên kết với các nguồn liên kết dữ liệu có chức năng tự động thông báo cho giao diện người dùng về các thay đổi trong dữ liệu. Bằng cách đó, các liên kết của bạn nhận biết được vòng đời và chỉ được kích hoạt khi giao diện người dùng hiển thị trên màn hình.
Tính năng liên kết dữ liệu hỗ trợ StateFlow
và LiveData
. Để biết thêm thông tin về cách sử dụng LiveData
trong liên kết dữ liệu, hãy xem bài viết Sử dụng LiveData để thông báo cho giao diện người dùng về các thay đổi về dữ liệu.
Sử dụng StateFlow
Nếu ứng dụng của bạn dùng Kotlin với coroutine, thì bạn có thể dùng các đối tượng StateFlow
làm nguồn liên kết dữ liệu. Để sử dụng đối tượng StateFlow
với lớp liên kết, hãy chỉ định chủ sở hữu vòng đời để xác định phạm vi của đối tượng StateFlow
. Ví dụ sau đây chỉ định hoạt động làm chủ sở hữu vòng đời sau khi lớp liên kết được tạo thực thể:
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
}
}
Như đã mô tả trong bài viết Liên kết khung hiển thị bố cục với Thành phần kiến trúc, tính năng liên kết dữ liệu hoạt động liền mạch với các đối tượng ViewModel
. Bạn có thể sử dụng StateFlow
và ViewModel
cùng nhau như sau:
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
Trong bố cục, hãy gán thuộc tính và phương thức của đối tượng ViewModel
cho các khung hiển thị tương ứng bằng cách sử dụng biểu thức liên kết, như trong ví dụ sau:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
Giao diện người dùng tự động cập nhật bất cứ khi nào giá trị tên của người dùng thay đổi.
Tắt tính năng hỗ trợ StateFlow
Đối với các ứng dụng sử dụng Kotlin và AndroidX, tính năng hỗ trợ StateFlow
sẽ tự động được đưa vào liên kết dữ liệu. Điều này có nghĩa là phần phụ thuộc coroutine sẽ tự động được đưa vào ứng dụng của bạn nếu chưa có phần phụ thuộc.
Bạn có thể chọn không sử dụng chức năng này bằng cách thêm đoạn mã sau vào tệp build.gradle
:
Groovy
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
Ngoài ra, bạn có thể tắt StateFlow
trên toàn cục trong dự án của mình bằng cách thêm
dòng sau vào tệp gradle.properties
:
Groovy
android.defaults.databinding.addKtx = false
Kotlin
android.defaults.databinding.addKtx = false
Tài nguyên khác
Để tìm hiểu thêm về liên kết dữ liệu, hãy xem các tài nguyên sau đây để biết thêm tài nguyên:
Mẫu
Lớp học lập trình
Bài đăng trên blog
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Mô-đun trạng thái đã lưu cho ViewModel
- Liên kết chế độ xem bố cục với Thành phần kiến trúc
- Tổng quan về thư viện Paging