استخدام عناصر البيانات القابلة للملاحظة

تشير الملاحظة إلى قدرة أحد الكائنات على إشعار الآخرين بشأن التغييرات في بياناته. تتيح لك مكتبة ربط البيانات جعل الكائنات أو الحقول أو المجموعات قابلة للملاحظة.

يمكنك استخدام أي كائن لربط البيانات، لكن تعديل الكائن لا يؤدي إلى تحديث واجهة المستخدم تلقائيًا. يمكنك استخدام ربط البيانات لمنح كائنات البيانات القدرة على إشعار الكائنات الأخرى، المعروفة باسم المستمعين، عند تغيير بياناتها. هناك ثلاثة أنواع من الفئات التي يمكن ملاحظتها: الحقول والمجموعات والكائنات.

عند ربط أحد كائنات البيانات القابلة للملاحظة هذه بواجهة المستخدم ويتغير أحد خصائص كائن البيانات، يتم تحديث واجهة المستخدم تلقائيًا.

الحقول القابلة للملاحظة

إذا كانت صفوفك لا تحتوي إلا على بعض السمات، قد لا يكون من المفيد إنشاء فئات تنفّذ واجهة Observable. وفي هذه الحالة، يمكنك استخدام الفئة العامة Observable والفئات الأساسية التالية الخاصة بملاحظة الحقول:

الحقول القابلة للملاحظة هي عناصر مستقلة يمكن ملاحظتها ولديها حقل واحد. تتجنب الإصدارات الأساسية وضع الملاكمة وفتح علبة المنتجات أثناء عمليات الوصول. لاستخدام هذه الآلية، أنشِئ السمة public final بلغة برمجة Java أو سمة للقراءة فقط في Kotlin، كما هو موضّح في المثال التالي:

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

للوصول إلى قيمة الحقل، استخدِم طريقتَي الموصِّل set() وget() أو استخدِم بنية سمة Kotlin:

Kotlin

user.firstName = "Google"
val age = user.age

Java

user.firstName.set("Google");
int age = user.age.get();

مجموعات بارزة

تستخدم بعض التطبيقات بنى ديناميكية للاحتفاظ بالبيانات. تسمح المجموعات القابلة للملاحظة بالوصول إلى هذه الهياكل باستخدام مفتاح. تكون الفئة ObservableArrayMap مفيدة عندما يكون المفتاح عبارة عن نوع مرجع، مثل String، كما هو موضّح في المثال التالي:

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

في التنسيق، يمكنك العثور على الخريطة باستخدام مفاتيح السلسلة، كما هو موضح في المثال التالي:

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</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"/>

تكون الفئة ObservableArrayList مفيدة عندما يكون المفتاح عددًا صحيحًا، على النحو التالي:

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

في التنسيق، يمكنك الوصول إلى القائمة من خلال الفهارس، كما هو موضح في المثال التالي:

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</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"/>

عناصر قابلة للملاحظة

تتيح الفئة التي تنفِّذ واجهة Observable تسجيل المستمعين الذين يريدون تلقّي إشعارات بالتغييرات في الخصائص من الكائن القابل للملاحظة.

تتضمن واجهة Observable آلية لإضافة مستمعين وإزالتهم، ولكن يمكنك تحديد وقت إرسال الإشعارات. لتسهيل عملية التطوير، توفّر "مكتبة ربط البيانات" الفئة BaseObservable التي تطبّق آلية تسجيل المستمع. وتكون فئة البيانات التي تستخدِم السمة BaseObservable مسؤولة عن إرسال الإشعارات في حال تغيير السمات. لتنفيذ ذلك، عليك إضافة تعليق توضيحي من Bindable إلى دالة getter واستدعاء الطريقة notifyPropertyChanged() في دالة setter، كما هو موضّح في المثال التالي:

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

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

عناصر تراعي مراحل النشاط

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

يتيح ربط البيانات استخدام StateFlow و LiveData. لمزيد من المعلومات حول استخدام LiveData في ربط البيانات، راجِع استخدام LiveData لإعلام واجهة المستخدم بالتغييرات في البيانات.

استخدام StateFlow

إذا كان تطبيقك يستخدم لغة Kotlin مع coroutine، يمكنك استخدام عناصر StateFlow كمصدر ربط البيانات. لاستخدام كائن StateFlow مع فئة الربط، حدِّد مالك دورة الحياة لتحديد نطاق الكائن StateFlow. يحدد المثال التالي النشاط كمالك لدورة الحياة بعد إنشاء مثيل للفئة المرتبطة:

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

كما هو موضّح في ربط طرق عرض التنسيق بالمكوّنات البنية، يعمل ربط البيانات بسلاسة مع عناصر ViewModel. يمكنك استخدام StateFlow وViewModel معًا على النحو التالي:

class ScheduleViewModel : ViewModel() {

    private val _username = MutableStateFlow<String>("")
    val username: StateFlow<String> = _username

    init {
        viewModelScope.launch {
            _username.value = Repository.loadUserName()
        }
    }
}

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

<TextView
    android:id="@+id/name"
    android:text="@{viewmodel.username}" />

يتم تعديل واجهة المستخدم تلقائيًا كلما تغيّرت قيمة اسم المستخدم.

إيقاف دعم StateFlow

بالنسبة إلى التطبيقات التي تستخدم Kotlin وAndroidX، يتم تضمين دعم StateFlow تلقائيًا في ميزة ربط البيانات. هذا يعني أنه يتم تضمين تبعية الكوروتينات تلقائيًا في التطبيق إذا لم تكن التبعية متاحة بالفعل.

ويمكنك إيقاف هذه الوظيفة من خلال إضافة ما يلي إلى ملف build.gradle:

رائع

android {
    ...
    dataBinding {
        addKtx = false
    }
}

Kotlin

android {
    ...
    dataBinding {
        addKtx = false
    }
}

وبدلاً من ذلك، يمكنك إيقاف StateFlow بشكل عام في مشروعك من خلال إضافة السطر التالي إلى ملف gradle.properties:

رائع

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

مراجع إضافية

لمعرفة المزيد من المعلومات عن ربط البيانات، راجِع ما يلي للاطّلاع على مراجع إضافية:

عيّنات

الدروس التطبيقية حول الترميز

مشاركات المدونة