পর্যবেক্ষণযোগ্য ডেটা অবজেক্ট নিয়ে কাজ করা

অবজার্ভেবিলিটি বলতে কোনও অবজেক্টের ডেটায় পরিবর্তন হলে সেই সম্পর্কে অন্যদের বিজ্ঞপ্তি পাঠানোর ক্ষমতাকে বোঝায়। ডেটা বাইন্ডিং লাইব্রেরি আপনাকে অবজেক্ট, ফিল্ড বা কালেকশন পর্যবেক্ষণযোগ্য করতে দেয়।

ডেটা বাইন্ডিংয়ের জন্য আপনি যেকোনও অবজেক্ট ব্যবহার করতে পারেন, তবে অবজেক্ট পরিবর্তন করলে UI অটোমেটিক আপডেট হয় না। ডেটা বাইন্ডিং ব্যবহার করে আপনি ডেটা অবজেক্টকে এমন ক্ষমতা দিতে পারেন যাতে ডেটা পরিবর্তন হলে তা অন্যান্য অবজেক্টকে—যাদের লিসেনার বলা হয়—জানাতে পারে। তিন ধরনের পর্যবেক্ষণযোগ্য ক্লাস আছে: ফিল্ড, কালেকশন এবং অবজেক্ট।

এইসব পর্যবেক্ষণযোগ্য ডেটা অবজেক্টের মধ্যে কোনও একটি UI-এর সাথে বাউন্ড করা থাকলে এবং ডেটা অবজেক্টের প্রপার্টি পরিবর্তন হলে, UI অটোমেটিক আপডেট হয়।

পর্যবেক্ষণযোগ্য ফিল্ড

আপনার ক্লাসে যদি মাত্র কয়েকটি প্রপার্টি থাকে, তাহলে Observable ইন্টারফেস প্রয়োগ করে ক্লাস তৈরি করার জন্য পরিশ্রম করা সার্থক নাও হতে পারে। এই ক্ষেত্রে, আপনি ফিল্ডগুলিকে পর্যবেক্ষণযোগ্য করতে জেনেরিক Observable ক্লাস এবং নিম্নলিখিত প্রিমিটিভ-নির্দিষ্ট ক্লাসগুলি ব্যবহার করতে পারেন:

পর্যবেক্ষণযোগ্য ফিল্ড হল স্বয়ংসম্পূর্ণ পর্যবেক্ষণযোগ্য অবজেক্ট যার একটিই ফিল্ড থাকে। প্রিমিটিভ ভার্সন অ্যাক্সেস অপারেশন চলাকালীন বক্সিং এবং আনবক্সিং এড়িয়ে চলে। এই মেকানিজম ব্যবহার করতে, Java প্রোগ্রামিং ল্যাঙ্গুয়েজে public final প্রপার্টি বা Kotlin-এ শুধু-পড়ার-উপযোগী প্রপার্টি তৈরি করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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 প্রপার্টি সিনট্যাক্স ব্যবহার করুন:

Kotlin

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

জাভা

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

জাভা

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

জাভা

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() মেথড কল করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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

জাভা

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 ক্লাস ফাইলে একটি এন্ট্রি তৈরি করে। ডেটা ক্লাসের জন্য মূল ক্লাস পরিবর্তন করা না গেলে, আপনি PropertyChangeRegistry অবজেক্ট ব্যবহার করে Observable ইন্টারফেস প্রয়োগ করতে পারেন যাতে দক্ষতার সাথে লিসেনারদের রেজিস্টার ও বিজ্ঞপ্তি পাঠানো যায়।

লাইফসাইকেল-অ্যাওয়ার অবজেক্ট

আপনার অ্যাপের লেআউট ডেটা বাইন্ডিং সোর্সের সাথেও বাইন্ড করতে পারে যা অটোমেটিক ডেটার পরিবর্তন সম্পর্কে UI-কে বিজ্ঞপ্তি দেয়। এইভাবে, আপনার বাইন্ডিং লাইফসাইকেল সম্পর্কে সচেতন এবং শুধুমাত্র তখনই ট্রিগার হয় যখন UI স্ক্রিনে দৃশ্যমান হয়।

ডেটা বাইন্ডিং StateFlow এবং LiveData-এ কাজ করে। ডেটা বাইন্ডিংয়ে LiveData ব্যবহার করা সম্পর্কে আরও তথ্যের জন্য, ডেটা পরিবর্তন সম্পর্কে UI-কে জানাতে LiveData ব্যবহার করুন দেখুন।

StateFlow ব্যবহার করুন

আপনার অ্যাপ যদি coroutines-এর সাথে 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
    }
}

আর্কিটেকচার কম্পোনেন্টে লেআউট ভিউ বাইন্ড করুন লিঙ্কে যেভাবে বর্ণনা করা হয়েছে, ডেটা বাইন্ডিং 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}" />

ব্যবহারকারীর নামের ভ্যালু পরিবর্তন হলেই UI অটোমেটিক আপডেট হয়।

StateFlow সহায়তা বন্ধ করুন

Kotlin ও AndroidX ব্যবহার করে এমন অ্যাপের ক্ষেত্রে, ডেটা বাইন্ডিংয়ের সাথে StateFlow-এর জন্য সহায়তা অটোমেটিক অন্তর্ভুক্ত করা হয়। এর অর্থ হল, আপনার অ্যাপে coroutines ডিপেন্ডেন্সি আগে থেকে উপলভ্য না থাকলে, এটি অটোমেটিক অন্তর্ভুক্ত করা হয়।

আপনার build.gradle ফাইলে নিম্নলিখিত তথ্য যোগ করে আপনি এই কার্যকারিতা থেকে বেরিয়ে আসতে পারবেন:

গ্ৰুভি

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

Kotlin

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

বিকল্প হিসেবে, gradle.properties ফাইলে নিম্নলিখিত লাইন যোগ করে আপনার প্রোজেক্টে গ্লোবাল লেভেলে StateFlow বন্ধ করতে পারবেন:

গ্ৰুভি

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

অতিরিক্ত রিসোর্স

ডেটা বাইন্ডিং সম্পর্কে আরও জানতে, অতিরিক্ত রিসোর্সের জন্য নিম্নলিখিতগুলি দেখুন:

নমুনা

কোডল্যাবস

ব্লগ পোস্ট