Liên kết chế độ xem bố cục với thành phần kiến trúc

Thư viện AndroidX bao gồm Thành phần kiến trúc, bạn có thể dùng thành phần này để thiết kế các ứng dụng mạnh mẽ, có thể kiểm thử và bảo trì. Thư viện liên kết dữ liệu hoạt động liền mạch với các Thành phần kiến trúc để đơn giản hoá hơn nữa quá trình phát triển giao diện người dùng. Các bố cục trong ứng dụng có thể liên kết với dữ liệu trong Thành phần cấu trúc, giúp bạn quản lý vòng đời của trình điều khiển giao diện người dùng và thông báo cho giao diện người dùng về các thay đổi trong dữ liệu.

Trang này cho biết cách kết hợp Thành phần cấu trúc vào ứng dụng của bạn để khai thác tối đa việc sử dụng Thư viện liên kết dữ liệu.

Sử dụng LiveData để thông báo cho giao diện người dùng về các thay đổi đối với dữ liệu

Bạn có thể sử dụng các đối tượng LiveData làm nguồn liên kết dữ liệu để tự động thông báo cho giao diện người dùng về các thay đổi trong dữ liệu. Để biết thêm thông tin về Thành phần cấu trúc này, hãy xem bài viết Tổng quan về LiveData.

Không giống như các đối tượng triển khai Observable (chẳng hạn như trường có thể quan sát), đối tượng LiveData biết về vòng đời của các đối tượng tiếp nhận dữ liệu đã đăng ký các thay đổi về dữ liệu. Kiến thức này mang lại nhiều lợi ích. Điều này được giải thích trong phần Ưu điểm của việc sử dụng LiveData. Trong Android Studio phiên bản 3.1 trở lên, bạn có thể thay thế các trường có thể quan sát bằng đối tượng LiveData trong mã liên kết dữ liệu.

Để sử dụng một đối tượng LiveData với lớp liên kết, bạn cần chỉ định chủ sở hữu vòng đời để xác định phạm vi của đối tượng LiveData. 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ể:

Kotlin

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.setLifecycleOwner(this)
    }
}

Java

class ViewModelActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Inflate view and obtain an instance of the binding class.
        UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

        // Specify the current activity as the lifecycle owner.
        binding.setLifecycleOwner(this);
    }
}

Bạn có thể sử dụng thành phần ViewModel, như giải thích trong phần sau, để liên kết dữ liệu với bố cục. Trong thành phần ViewModel, bạn có thể sử dụng đối tượng LiveData để chuyển đổi dữ liệu hoặc hợp nhất nhiều nguồn dữ liệu. Ví dụ sau đây cho biết cách chuyển đổi dữ liệu trong ViewModel:

Kotlin

class ScheduleViewModel : ViewModel() {
    val userName: LiveData

    init {
        val result = Repository.userName
        userName = Transformations.map(result) { result -> result.value }
    }
}

Java

class ScheduleViewModel extends ViewModel {
    LiveData username;

    public ScheduleViewModel() {
        String result = Repository.userName;
        userName = Transformations.map(result, result -> result.value);
    }
}

Sử dụng ViewModel để quản lý dữ liệu liên quan đến giao diện người dùng

Thư viện liên kết dữ liệu hoạt động liền mạch với các thành phần ViewModel. ViewModel hiển thị dữ liệu mà bố cục quan sát và phản ứng với các thay đổi của bố cục đó. Việc sử dụng các thành phần ViewModel với Thư viện liên kết dữ liệu cho phép bạn di chuyển logic giao diện người dùng ra khỏi bố cục và vào các thành phần để dễ kiểm thử hơn. Thư viện liên kết dữ liệu đảm bảo các chế độ xem được liên kết và không bị liên kết với nguồn dữ liệu khi cần. Hầu hết công việc còn lại là đảm bảo rằng bạn hiển thị đúng dữ liệu. Để biết thêm thông tin về Thành phần cấu trúc này, hãy xem bài viết Tổng quan về ViewModel.

Để sử dụng thành phần ViewModel với Thư viện liên kết dữ liệu, bạn phải tạo thực thể thành phần (kế thừa từ lớp ViewModel), lấy một bản sao của lớp liên kết và gán thành phần ViewModel cho một thuộc tính trong lớp liên kết. Ví dụ sau cho biết cách sử dụng thành phần với thư viện:

Kotlin

class ViewModelActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // Obtain the ViewModel component.
        val userModel: UserModel by viewModels()

        // Inflate view and obtain an instance of the binding class.
        val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)

        // Assign the component to a property in the binding class.
        binding.viewmodel = userModel
    }
}

Java

class ViewModelActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Obtain the ViewModel component.
        UserModel userModel = new ViewModelProvider(this).get(UserModel.class);

        // Inflate view and obtain an instance of the binding class.
        UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);

        // Assign the component to a property in the binding class.
        binding.viewmodel = userModel;
    }
}

Trong bố cục, hãy chỉ định các thuộc tính và phương thức của thành phần ViewModel cho các chế độ xem tương ứng bằng cách sử dụng biểu thức liên kết, như trong ví dụ sau:

<CheckBox
    android:id="@+id/rememberMeCheckBox"
    android:checked="@{viewmodel.rememberMe}"
    android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />

Sử dụng ViewModel có thể quan sát để kiểm soát nhiều hơn đối với các bộ chuyển đổi liên kết

Bạn có thể sử dụng thành phần ViewModel triển khai giao diện Observable để thông báo cho các thành phần ứng dụng khác về các thay đổi trong dữ liệu, tương tự như cách bạn sử dụng đối tượng LiveData.

Có những trường hợp bạn có thể muốn sử dụng thành phần ViewModel sẽ triển khai giao diện Observable thay vì sử dụng các đối tượng LiveData, ngay cả khi bạn mất khả năng quản lý vòng đời của LiveData. Việc sử dụng thành phần ViewModel triển khai Observable sẽ giúp bạn có nhiều quyền kiểm soát hơn đối với các bộ chuyển đổi liên kết trong ứng dụng. Ví dụ: mẫu này giúp bạn có nhiều quyền kiểm soát hơn đối với các thông báo khi dữ liệu thay đổi; cũng như chỉ định phương thức tuỳ chỉnh để đặt giá trị của một thuộc tính trong liên kết dữ liệu hai chiều.

Để triển khai thành phần ViewModel có thể quan sát, bạn phải tạo một lớp kế thừa từ lớp ViewModel và triển khai giao diện Observable. Bạn có thể cung cấp logic tuỳ chỉnh khi đối tượng tiếp nhận dữ liệu đăng ký hoặc huỷ đăng ký nhận thông báo bằng các phương thức addOnPropertyChangedCallback()removeOnPropertyChangedCallback(). Bạn cũng có thể cung cấp logic tuỳ chỉnh chạy khi các thuộc tính thay đổi trong phương thức notifyPropertyChanged(). Mã ví dụ sau đây cho thấy cách triển khai một ViewModel có thể quan sát được:

Kotlin

/**
 * A ViewModel that is also an Observable,
 * to be used with the Data Binding Library.
 */
open class ObservableViewModel : ViewModel(), Observable {
    private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()

    override fun addOnPropertyChangedCallback(
            callback: Observable.OnPropertyChangedCallback) {
        callbacks.add(callback)
    }

    override fun removeOnPropertyChangedCallback(
            callback: Observable.OnPropertyChangedCallback) {
        callbacks.remove(callback)
    }

    /**
     * Notifies observers that all properties of this instance have changed.
     */
    fun notifyChange() {
        callbacks.notifyCallbacks(this, 0, null)
    }

    /**
     * Notifies observers that a specific property has changed. The getter for the
     * property that changes must be marked with the @Bindable annotation to
     * generate a field in the BR class to be used as the fieldId parameter.
     *
     * @param fieldId The generated BR id for the Bindable field.
     */
    fun notifyPropertyChanged(fieldId: Int) {
        callbacks.notifyCallbacks(this, fieldId, null)
    }
}

Java

/**
 * A ViewModel that is also an Observable,
 * to be used with the Data Binding Library.
 */
class ObservableViewModel extends ViewModel implements Observable {
    private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();

    @Override
    protected void addOnPropertyChangedCallback(
            Observable.OnPropertyChangedCallback callback) {
        callbacks.add(callback);
    }

    @Override
    protected void removeOnPropertyChangedCallback(
            Observable.OnPropertyChangedCallback callback) {
        callbacks.remove(callback);
    }

    /**
     * Notifies observers that all properties of this instance have changed.
     */
    void notifyChange() {
        callbacks.notifyCallbacks(this, 0, null);
    }

    /**
     * Notifies observers that a specific property has changed. The getter for the
     * property that changes must be marked with the @Bindable annotation to
     * generate a field in the BR class to be used as the fieldId parameter.
     *
     * @param fieldId The generated BR id for the Bindable field.
     */
    void notifyPropertyChanged(int fieldId) {
        callbacks.notifyCallbacks(this, fieldId, null);
    }
}

Tài nguyên khác

Để tìm hiểu thêm về tính năng liên kết dữ liệu, hãy tham khảo thêm các tài nguyên sau đây.