کار کردن با اشیای داده‌های دیده‌شدنی

مشاهده‌پذیری به توانایی یک شیء برای مطلع کردن دیگران از تغییرات داده‌هایش اشاره دارد. «کتابخانه اتصال داده» به شما امکان می‌دهد اشیاء، فیلدها، یا مجموعه‌ها را قابل‌مشاهده کنید.

می‌توانید از هر شیئی برای اتصال داده استفاده کنید، اما اصلاح شیء به‌طور خودکار باعث به‌روزرسانی واسط کاربر نمی‌شود. می‌توانید از اتصال داده استفاده کنید تا به اشیای داده‌تان این توانایی را بدهید که وقتی داده‌هایشان تغییر می‌کند به اشیای دیگر (که شنونده نامیده می‌شوند) اطلاع دهند. سه نوع کلاس قابل‌مشاهده وجود دارد: فیلدها، مجموعه‌ها، و اشیاء.

وقتی یکی از این اشیای داده‌های دیده‌شدنی به واسط کاربر متصل می‌شود و یکی از ویژگی‌های شیء داده تغییر می‌کند، واسط کاربر به‌طور خودکار به‌روز می‌شود.

فیلدهای دیده‌شدنی

اگر کلاس‌هایتان فقط چند ویژگی دارند، ممکن است ارزش تلاش برای ایجاد کلاس‌هایی را که رابط Observable را پیاده‌سازی می‌کنند نداشته باشد. در این مورد، می‌توانید از کلاس عمومی Observable و کلاس‌های خاص اولیه زیر برای قابل‌مشاهده کردن فیلدها استفاده کنید:

فیلدهای قابل‌مشاهده اشیاء قابل‌مشاهده مستقل هستند که یک فیلد دارند. نسخه‌های اولیه از بسته‌بندی و باز کردن بسته‌بندی درطول عملیات دسترسی جلوگیری می‌کنند. برای استفاده از این سازوکار، یک ویژگی public final در زبان برنامه‌نویسی Java یا یک ویژگی فقط خواندنی در Kotlin ایجاد کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

class User {
    val firstName = ObservableField<String>()
    val lastName = ObservableField<String>()
    val age = ObservableInt()
}

جاوا

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 استفاده کنید:

کاتلین

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

جاوا

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

مجموعه‌های قابل‌مشاهده

برخی‌از برنامه‌ها از ساختارهای پویا برای نگهداری داده‌ها استفاده می‌کنند. مجموعه‌های قابل‌مشاهده امکان دسترسی به این ساختارها را بااستفاده از کلید فراهم می‌کنند. کلاس ObservableArrayMap زمانی مفید است که کلید از نوع مرجع باشد، مانند String، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

ObservableArrayMap<String, Any>().apply {
    put("firstName", "Google")
    put("lastName", "Inc.")
    put("age", 17)
}

جاوا

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 زمانی مفید است که کلید یک عدد صحیح باشد، به‌صورت زیر:

کاتلین

ObservableArrayList<Any>().apply {
    add("Google")
    add("Inc.")
    add(17)
}

جاوا

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 را به گیرنده اختصاص دهید و روش notifyPropertyChanged() را در تنظیم‌کننده فراخوانی کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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 با روال‌های مشترک استفاده می‌کند، می‌توانید از اشیاء 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
    }
}

همان‌طور که در Bind layout views to Architecture Components شرح داده شده است، اتصال داده به‌طور یکپارچه با اشیاء 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 به‌طور خودکار با اتصال داده گنجانده می‌شود. این یعنی وابستگی coroutines به‌طور خودکار در برنامه شما گنجانده می‌شود، اگر این وابستگی ازقبل دردسترس نباشد.

با افزودن موارد زیر به فایل build.gradle می‌توانید از این عملکرد انصراف دهید:

شیک

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

کاتلین

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

یا می‌توانید با افزودن خط زیر به فایل gradle.properties،‏ StateFlow را به‌طور سراسری در پروژه‌تان غیرفعال کنید:

شیک

android.defaults.databinding.addKtx = false

کاتلین

android.defaults.databinding.addKtx = false

منابع بیشتر

برای کسب اطلاعات بیشتر درباره اتصال داده، منابع اضافی زیر را ببینید:

نمونه‌ها

Codelabs

پست‌های وبلاگ