Mengikat tampilan tata letak ke Komponen Arsitektur

Library AndroidX menyertakan Komponen Arsitektur, yang dapat Anda gunakan untuk mendesain aplikasi yang tangguh, dapat diuji, dan mudah dikelola. Library Data Binding berfungsi lancar dengan Komponen Arsitektur untuk lebih menyederhanakan pengembangan UI Anda. Tata letak di aplikasi Anda dapat mengikat data dalam Komponen Arsitektur, yang membantu Anda mengelola siklus proses pengontrol UI dan memberi tahu UI tentang perubahan data.

Halaman ini menunjukkan cara menggabungkan Komponen Arsitektur ke dalam aplikasi Anda untuk mendapatkan hasil maksimal dari penggunaan Library Data Binding.

Menggunakan LiveData untuk memberitahukan perubahan data ke UI

Anda dapat menggunakan objek LiveData sebagai sumber data binding untuk otomatis memberitahukan perubahan data ke UI. Untuk informasi selengkapnya tentang Komponen Arsitektur ini, lihat ringkasan LiveData.

Tidak seperti objek yang menerapkan Observable—seperti kolom observable—objek LiveData mengetahui siklus proses observer yang berlangganan perubahan data. Pengetahuan ini memberikan banyak manfaat, seperti yang dijelaskan di Manfaat menggunakan LiveData. Di Android Studio versi 3.1 dan yang lebih baru, Anda dapat mengganti kolom yang dapat diamati dengan objek LiveData di kode data binding.

Untuk menggunakan objek LiveData dengan class binding, Anda harus menentukan pemilik siklus proses untuk menentukan cakupan objek LiveData. Contoh berikut menentukan aktivitas sebagai pemilik siklus proses setelah instance class binding dibuat:

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);
    }
}

Anda dapat menggunakan komponen ViewModel, seperti yang dijelaskan di bagian berikut, untuk mengikat data ke tata letak. Dalam komponen ViewModel, Anda dapat menggunakan objek LiveData untuk mengubah data atau menggabungkan beberapa sumber data. Contoh berikut menunjukkan cara mengubah data dalam 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);
    }
}

Menggunakan ViewModel untuk mengelola data terkait UI

Library Data Binding berfungsi lancar dengan komponen ViewModel. ViewModel mengekspos data yang diamati dan direspons oleh tata letak terhadap perubahannya. Penggunaan komponen ViewModel dengan Library Data Binding memungkinkan Anda memindahkan logika UI dari tata letak dan ke dalam komponen, yang lebih mudah untuk diuji. Library Data Binding memastikan tampilan terikat dan tidak terikat dari sumber data saat diperlukan. Sebagian besar pekerjaan yang tersisa terdiri dari memastikan bahwa Anda mengekspos data yang benar. Untuk informasi selengkapnya tentang Komponen Arsitektur ini, lihat ringkasan ViewModel.

Untuk menggunakan komponen ViewModel dengan Library Data Binding, Anda harus membuat instance komponen—yang diwarisi dari class ViewModel, mendapatkan instance class binding, dan menetapkan komponen ViewModel ke properti di class binding. Contoh berikut menunjukkan cara menggunakan komponen dengan library:

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;
    }
}

Di tata letak, tetapkan properti dan metode komponen ViewModel ke tampilan yang terkait menggunakan ekspresi binding, seperti yang ditunjukkan pada contoh berikut:

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

Menggunakan ViewModel yang Dapat Diobservasi untuk mendapatkan kontrol lebih besar atas adaptor binding

Anda dapat menggunakan komponen ViewModel yang mengimplementasikan antarmuka Observable untuk memberi tahu komponen aplikasi lain tentang perubahan data, mirip dengan cara menggunakan objek LiveData.

Ada situasi saat Anda mungkin lebih suka menggunakan komponen ViewModel yang mengimplementasikan antarmuka Observable daripada menggunakan objek LiveData, meskipun Anda kehilangan kemampuan pengelolaan siklus proses LiveData. Penggunaan komponen ViewModel yang mengimplementasikan Observable memberi Anda kontrol lebih besar atas adaptor binding di aplikasi. Misalnya, pola ini memberi Anda kontrol lebih besar atas notifikasi saat data berubah; hal ini juga memungkinkan Anda menentukan metode kustom untuk menetapkan nilai atribut dalam data binding dua arah.

Untuk mengimplementasikan komponen ViewModel yang dapat diamati, Anda harus membuat class yang diwarisi dari class ViewModel dan mengimplementasikan antarmuka Observable. Anda dapat memberikan logika kustom saat observer berlangganan atau berhenti berlangganan notifikasi menggunakan metode addOnPropertyChangedCallback() dan removeOnPropertyChangedCallback(). Anda juga dapat menyediakan logika kustom yang berjalan saat properti berubah dalam metode notifyPropertyChanged(). Contoh kode berikut menunjukkan cara menerapkan ViewModel yang dapat diamati:

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);
    }
}

Referensi lainnya

Untuk mempelajari data binding lebih lanjut, lihat referensi tambahan berikut.