ربط طرق عرض التنسيق بمكوّنات البنية

تتضمن مكتبة AndroidX مكونات بنية التطبيق التي يمكنك استخدامها لتصميم تطبيقات قوية وقابلة للاختبار وقابلة للصيانة. تعمل مكتبة ربط البيانات بسلاسة مع مكونات البنية لتبسيط تطوير واجهة المستخدم لديك. يمكن للتخطيطات في تطبيقك الارتباط بالبيانات الموجودة في مكونات البنية، مما يساعدك في إدارة دورة حياة وحدة التحكم في واجهة المستخدم وإبلاغ واجهة المستخدم بالتغييرات في البيانات.

توضح هذه الصفحة كيفية دمج مكونات البنية في تطبيقك لتحقيق أقصى استفادة من استخدام مكتبة ربط البيانات.

استخدام البيانات المباشرة لإرسال إشعار إلى واجهة المستخدم بشأن التغييرات في البيانات

يمكنك استخدام كائنات LiveData كمصدر ربط البيانات لإشعار واجهة المستخدم تلقائيًا بالتغييرات في البيانات. للحصول على مزيد من المعلومات حول مكوّن البنية هذا، راجع نظرة عامة على LiveData.

على عكس الكائنات التي تطبّق Observable، مثل الحقول القابلة للملاحظة،LiveData تتعرّف الكائنات على دورة حياة المشاهِدين المشتركين في تغييرات البيانات. وتوفّر لك هذه المعرفة العديد من المزايا، كما هو موضّح في مزايا استخدام LiveData. في الإصدار 3.1 من "استوديو Android" والإصدارات الأحدث، يمكنك استبدال الحقول القابلة للتتبّع بعناصر LiveData في رمز ربط البيانات.

لاستخدام كائن LiveData مع فئة الربط، عليك تحديد مالك دورة حياة لتحديد نطاق الكائن LiveData. يحدد المثال التالي النشاط كمالك لدورة الحياة بعد إنشاء مثيل للفئة المرتبطة:

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

يمكنك استخدام مكوِّن ViewModel، كما هو موضّح في القسم التالي، لربط البيانات بالتنسيق. في المكوِّن ViewModel، يمكنك استخدام الكائن LiveData لتحويل البيانات أو دمج مصادر بيانات متعددة. يوضّح المثال التالي كيفية تحويل البيانات في 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);
    }
}

استخدام ViewModel لإدارة البيانات المتعلقة بواجهة المستخدم

تعمل "مكتبة ربط البيانات" بسلاسة مع مكوّنات ViewModel. تعرض السمة ViewModel البيانات التي يلاحظها التنسيق ويتفاعل معها. يتيح لك استخدام مكوّنات ViewModel مع "مكتبة ربط البيانات" نقل منطق واجهة المستخدم من التنسيقات إلى المكوّنات، ما يسهّل اختبارها. تضمن مكتبة ربط البيانات ربط طرق العرض بمصدر البيانات وإلغاء ربطها بمصدر البيانات عند الحاجة. يتكون معظم العمل المتبقي من التأكد من أنك تعرض البيانات الصحيحة. لمزيد من المعلومات حول مكوِّن البنية هذا، راجع نظرة عامة ViewModel.

لاستخدام المكوِّن ViewModel مع "مكتبة ربط البيانات"، عليك إنشاء نسخة افتراضية من المكوِّن، وهو الذي يكتسب من الفئة ViewModel، ويحصل على مثيل لفئة الربط، وعيِّن المكوِّن ViewModel إلى خاصية في فئة الربط. يوضح المثال التالي كيفية استخدام المكون مع المكتبة:

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

في التنسيق، حدِّد خصائص وأساليب مكوّن ViewModel لطرق العرض المقابلة باستخدام تعبيرات ربط، كما هو موضّح في المثال التالي:

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

استخدام نموذج عرض قابل للملاحظة لمزيد من التحكّم في محوّلات الربط

يمكنك استخدام مكوّن ViewModel ينفّذ واجهة Observable لإشعار مكوّنات التطبيق الأخرى بالتغييرات التي تطرأ على البيانات، بالطريقة نفسها التي تستخدم بها عنصر LiveData.

هناك مواقف قد تفضّل فيها استخدام المكوِّن ViewModel الذي ينفِّذ واجهة Observable على استخدام كائنات LiveData، حتى إذا فقدت إمكانات إدارة مراحل النشاط في LiveData. يمنحك استخدام مكوِّن ViewModel ينفّذ Observable المزيد من التحكّم في محوّلات الربط في تطبيقك. على سبيل المثال، يمنحك هذا النمط مزيدًا من التحكّم في الإشعارات عند تغيير البيانات، ويتيح لك أيضًا تحديد طريقة مخصّصة لضبط قيمة سمة في ربط البيانات ثنائي الاتجاه.

لتنفيذ مكوِّن ViewModel يمكن ملاحظته، عليك إنشاء فئة تكتسب من الفئة ViewModel وتنفِّذ واجهة Observable. يمكنك توفير منطق مخصص عندما يشترك المراقب في الإشعارات أو يلغي الاشتراك فيها باستخدام الطريقتين addOnPropertyChangedCallback() و removeOnPropertyChangedCallback(). يمكنك أيضًا توفير منطق مخصّص يتم تشغيله عند تغيير الخصائص في إجراء notifyPropertyChanged(). يوضِّح مثال الرمز التالي كيفية تنفيذ دالة ViewModel قابلة للملاحظة:

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

مراجع إضافية

لمعرفة المزيد حول ربط البيانات، راجع الموارد الإضافية التالية.