লাইভডেটা ওভারভিউ অ্যান্ড্রয়েড জেটপ্যাকের অংশ।

LiveData হল একটি পর্যবেক্ষণযোগ্য ডেটা ধারক শ্রেণী। একটি নিয়মিত পর্যবেক্ষণযোগ্য থেকে ভিন্ন, লাইভডেটা হল জীবনচক্র-সচেতন, যার অর্থ এটি ক্রিয়াকলাপ, টুকরো বা পরিষেবাগুলির মতো অন্যান্য অ্যাপ উপাদানগুলির জীবনচক্রকে সম্মান করে৷ এই সচেতনতা নিশ্চিত করে যে LiveData শুধুমাত্র অ্যাপ্লিকেশান কম্পোনেন্ট পর্যবেক্ষকদের আপডেট করে যেগুলি একটি সক্রিয় জীবনচক্র অবস্থায় রয়েছে।

LiveData একটি পর্যবেক্ষককে বিবেচনা করে, যা Observer শ্রেণী দ্বারা প্রতিনিধিত্ব করা হয়, যদি তার জীবনচক্র STARTED বা RESUMED অবস্থায় থাকে তবে একটি সক্রিয় অবস্থায় থাকবে। LiveData শুধুমাত্র সক্রিয় পর্যবেক্ষকদের আপডেট সম্পর্কে অবহিত করে। LiveData অবজেক্ট দেখার জন্য নিবন্ধিত নিষ্ক্রিয় পর্যবেক্ষকদের পরিবর্তন সম্পর্কে অবহিত করা হয় না।

আপনি একটি অবজেক্টের সাথে পেয়ার করা একটি পর্যবেক্ষক নিবন্ধন করতে পারেন যা LifecycleOwner ইন্টারফেস প্রয়োগ করে। এই সম্পর্কটি পর্যবেক্ষককে অপসারণ করার অনুমতি দেয় যখন সংশ্লিষ্ট Lifecycle বস্তুর অবস্থা DESTROYED এ পরিবর্তিত হয়। এটি বিশেষত ক্রিয়াকলাপ এবং টুকরোগুলির জন্য উপযোগী কারণ তারা নিরাপদে LiveData অবজেক্টগুলি পর্যবেক্ষণ করতে পারে এবং ফাঁসের বিষয়ে চিন্তা করতে পারে না — ক্রিয়াকলাপ এবং টুকরোগুলি যখন তাদের জীবনচক্র ধ্বংস হয়ে যায় তখন তাত্ক্ষণিকভাবে সদস্যতা ত্যাগ করা হয়৷

কিভাবে LiveData ব্যবহার করবেন সে সম্পর্কে আরও তথ্যের জন্য, LiveData অবজেক্টের সাথে কাজ দেখুন।

LiveData ব্যবহারের সুবিধা

LiveData ব্যবহার করে নিম্নলিখিত সুবিধাগুলি প্রদান করে:

আপনার UI আপনার ডেটা অবস্থার সাথে মেলে তা নিশ্চিত করে
LiveData পর্যবেক্ষক প্যাটার্ন অনুসরণ করে। অন্তর্নিহিত ডেটা পরিবর্তনের সময় LiveData Observer অবজেক্টগুলিকে অবহিত করে। আপনি এই Observer অবজেক্টগুলিতে UI আপডেট করতে আপনার কোড একত্রিত করতে পারেন। এইভাবে, প্রতিবার অ্যাপের ডেটা পরিবর্তন করার সময় আপনাকে UI আপডেট করতে হবে না কারণ পর্যবেক্ষক আপনার জন্য এটি করে।
কোন মেমরি ফাঁস
পর্যবেক্ষকরা Lifecycle অবজেক্টের সাথে আবদ্ধ থাকে এবং তাদের সাথে সম্পর্কিত জীবনচক্র ধ্বংস হয়ে গেলে নিজেদের পরে পরিষ্কার করে।
বন্ধ কার্যকলাপের কারণে কোন ক্র্যাশ
যদি পর্যবেক্ষকের জীবনচক্র নিষ্ক্রিয় থাকে, যেমন ব্যাক স্ট্যাকের একটি কার্যকলাপের ক্ষেত্রে, তাহলে এটি কোনো LiveData ইভেন্ট পায় না।
আর ম্যানুয়াল লাইফসাইকেল হ্যান্ডলিং নেই
UI উপাদানগুলি কেবল প্রাসঙ্গিক ডেটা পর্যবেক্ষণ করে এবং পর্যবেক্ষণ বন্ধ বা পুনরায় শুরু করে না। লাইভডেটা স্বয়ংক্রিয়ভাবে এই সমস্তগুলি পরিচালনা করে কারণ এটি পর্যবেক্ষণ করার সময় প্রাসঙ্গিক জীবনচক্রের অবস্থার পরিবর্তন সম্পর্কে সচেতন।
সর্বদা আপ টু ডেট ডেটা
যদি একটি জীবনচক্র নিষ্ক্রিয় হয়ে যায়, এটি আবার সক্রিয় হওয়ার পরে সর্বশেষ ডেটা পায়। উদাহরণস্বরূপ, ব্যাকগ্রাউন্ডে থাকা একটি অ্যাক্টিভিটি ফোরগ্রাউন্ডে ফিরে আসার সাথে সাথেই সর্বশেষ ডেটা গ্রহণ করে।
সঠিক কনফিগারেশন পরিবর্তন
ডিভাইসের ঘূর্ণনের মতো কনফিগারেশন পরিবর্তনের কারণে যদি কোনও কার্যকলাপ বা খণ্ডটি পুনরায় তৈরি করা হয়, এটি অবিলম্বে সর্বশেষ উপলব্ধ ডেটা গ্রহণ করে।
সম্পদ ভাগ করা
আপনি সিস্টেম পরিষেবাগুলি মোড়ানোর জন্য সিঙ্গলটন প্যাটার্ন ব্যবহার করে একটি LiveData অবজেক্ট প্রসারিত করতে পারেন যাতে সেগুলি আপনার অ্যাপে ভাগ করা যায়। LiveData অবজেক্টটি একবার সিস্টেম পরিষেবার সাথে সংযোগ করে এবং তারপরে যেকোন পর্যবেক্ষক যার সংস্থান প্রয়োজন সে কেবল LiveData অবজেক্টটি দেখতে পারে। আরও তথ্যের জন্য, LiveData প্রসারিত দেখুন।

LiveData অবজেক্টের সাথে কাজ করুন

LiveData অবজেক্টের সাথে কাজ করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. একটি নির্দিষ্ট ধরনের ডেটা ধরে রাখতে LiveData এর একটি উদাহরণ তৈরি করুন। এটি সাধারণত আপনার ViewModel ক্লাসের মধ্যে করা হয়।
  2. একটি Observer অবজেক্ট তৈরি করুন যা onChanged() পদ্ধতিকে সংজ্ঞায়িত করে, যা নিয়ন্ত্রণ করে যখন LiveData অবজেক্টের ধারণকৃত ডেটা পরিবর্তন হয়। আপনি সাধারণত একটি UI কন্ট্রোলারে একটি Observer অবজেক্ট তৈরি করেন, যেমন একটি কার্যকলাপ বা খণ্ড।
  3. observe() পদ্ধতি ব্যবহার করে LiveData অবজেক্টের সাথে Observer অবজেক্ট সংযুক্ত করুন। observe() পদ্ধতি একটি LifecycleOwner অবজেক্ট নেয়। এটি Observer অবজেক্টকে LiveData অবজেক্টে সাবস্ক্রাইব করে যাতে এটি পরিবর্তন সম্পর্কে অবহিত হয়। আপনি সাধারণত একটি UI কন্ট্রোলারে Observer অবজেক্ট সংযুক্ত করেন, যেমন একটি কার্যকলাপ বা খণ্ড।

আপনি যখন LiveData অবজেক্টে সংরক্ষিত মান আপডেট করেন, তখন এটি সমস্ত নিবন্ধিত পর্যবেক্ষককে ট্রিগার করে যতক্ষণ না সংযুক্ত LifecycleOwner সক্রিয় অবস্থায় থাকে।

LiveData UI কন্ট্রোলার পর্যবেক্ষকদের আপডেটে সদস্যতা নিতে দেয়। যখন LiveData অবজেক্টের কাছে থাকা ডেটা পরিবর্তিত হয়, তখন UI স্বয়ংক্রিয়ভাবে প্রতিক্রিয়া হিসাবে আপডেট হয়।

LiveData অবজেক্ট তৈরি করুন

LiveData হল একটি মোড়ক যা যেকোন ডেটার সাথে ব্যবহার করা যেতে পারে, এমন বস্তু সহ যা Collections বাস্তবায়ন করে, যেমন List । একটি LiveData অবজেক্ট সাধারণত একটি ViewModel অবজেক্টের মধ্যে সংরক্ষণ করা হয় এবং একটি গেটার পদ্ধতির মাধ্যমে অ্যাক্সেস করা হয়, যেমনটি নিম্নলিখিত উদাহরণে প্রদর্শিত হয়েছে:

কোটলিন

class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // Rest of the ViewModel...
}

জাভা

public class NameViewModel extends ViewModel {

    // Create a LiveData with a String
    private MutableLiveData<String> currentName;

    public MutableLiveData<String> getCurrentName() {
        if (currentName == null) {
            currentName = new MutableLiveData<String>();
        }
        return currentName;
    }

    // Rest of the ViewModel...
}

প্রাথমিকভাবে, একটি LiveData অবজেক্টের ডেটা সেট করা হয় না।

আপনি ViewModel গাইডে ViewModel ক্লাসের সুবিধা এবং ব্যবহার সম্পর্কে আরও পড়তে পারেন।

LiveData অবজেক্ট পর্যবেক্ষণ করুন

বেশিরভাগ ক্ষেত্রে, একটি অ্যাপ কম্পোনেন্টের onCreate() পদ্ধতি হল নিম্নলিখিত কারণে একটি LiveData অবজেক্ট পর্যবেক্ষণ শুরু করার সঠিক জায়গা:

  • সিস্টেমটি একটি কার্যকলাপ বা খণ্ডের onResume() পদ্ধতি থেকে অপ্রয়োজনীয় কল না করে তা নিশ্চিত করতে।
  • অ্যাক্টিভিটি বা ফ্র্যাগমেন্টের ডেটা আছে তা নিশ্চিত করার জন্য এটি সক্রিয় হওয়ার সাথে সাথে এটি প্রদর্শন করতে পারে। একটি অ্যাপ কম্পোনেন্ট STARTED অবস্থায় থাকা মাত্রই, এটি পর্যবেক্ষণ করা LiveData অবজেক্ট থেকে সাম্প্রতিকতম মান গ্রহণ করে। এটি শুধুমাত্র তখনই ঘটে যখন পর্যবেক্ষণ করা LiveData অবজেক্ট সেট করা থাকে।

সাধারণত, লাইভডেটা শুধুমাত্র ডেটা পরিবর্তিত হলেই আপডেট প্রদান করে এবং শুধুমাত্র সক্রিয় পর্যবেক্ষকদের কাছে। এই আচরণের একটি ব্যতিক্রম হল যে পর্যবেক্ষকরা একটি আপডেট পান যখন তারা একটি নিষ্ক্রিয় থেকে একটি সক্রিয় অবস্থায় পরিবর্তিত হয়। উপরন্তু, যদি পর্যবেক্ষক নিষ্ক্রিয় থেকে সক্রিয় থেকে দ্বিতীয়বার পরিবর্তিত হয়, তবে এটি শুধুমাত্র একটি আপডেট পায় যদি শেষবার সক্রিয় হওয়ার পর থেকে মানটি পরিবর্তিত হয়।

নিম্নলিখিত নমুনা কোডটি ব্যাখ্যা করে কিভাবে একটি LiveData অবজেক্ট পর্যবেক্ষণ করা শুরু করতে হয়:

কোটলিন

class NameActivity : AppCompatActivity() {

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val model: NameViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Other code to setup the activity...

        // Create the observer which updates the UI.
        val nameObserver = Observer<String> { newName ->
            // Update the UI, in this case, a TextView.
            nameTextView.text = newName
        }

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.currentName.observe(this, nameObserver)
    }
}

জাভা

public class NameActivity extends AppCompatActivity {

    private NameViewModel model;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Other code to setup the activity...

        // Get the ViewModel.
        model = new ViewModelProvider(this).get(NameViewModel.class);

        // Create the observer which updates the UI.
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update the UI, in this case, a TextView.
                nameTextView.setText(newName);
            }
        };

        // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
        model.getCurrentName().observe(this, nameObserver);
    }
}

পরামিতি হিসাবে পাস করা nameObserver এর সাথে observe() ডাকার পরে, mCurrentName এ সংরক্ষিত সাম্প্রতিকতম মান প্রদান করে onChanged() অবিলম্বে আহ্বান করা হয়। যদি LiveData অবজেক্ট mCurrentName এ একটি মান সেট না করে থাকে, onChanged() বলা হবে না।

লাইভডেটা অবজেক্ট আপডেট করুন

সঞ্চিত ডেটা আপডেট করার জন্য LiveData-এর কোনো সর্বজনীনভাবে উপলব্ধ পদ্ধতি নেই। MutableLiveData ক্লাস setValue(T) এবং postValue(T) পদ্ধতিগুলিকে সর্বজনীনভাবে প্রকাশ করে এবং আপনি যদি একটি LiveData অবজেক্টে সঞ্চিত মান সম্পাদনা করতে চান তবে আপনাকে অবশ্যই এগুলি ব্যবহার করতে হবে। সাধারণত ViewModelMutableLiveData ব্যবহার করা হয় এবং তারপর ViewModel শুধুমাত্র অপরিবর্তনীয় LiveData অবজেক্টগুলিকে পর্যবেক্ষকদের কাছে প্রকাশ করে।

আপনি পর্যবেক্ষক সম্পর্ক সেট আপ করার পরে, আপনি LiveData অবজেক্টের মান আপডেট করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণ দ্বারা চিত্রিত করা হয়েছে, যা ব্যবহারকারী একটি বোতামে ট্যাপ করলে সমস্ত পর্যবেক্ষককে ট্রিগার করে:

কোটলিন

button.setOnClickListener {
    val anotherName = "John Doe"
    model.currentName.setValue(anotherName)
}

জাভা

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});

উদাহরণে setValue(T) কল করার ফলে পর্যবেক্ষকরা তাদের onChanged() পদ্ধতিগুলিকে John Doe মান দিয়ে কল করেন। উদাহরণে একটি বোতাম টিপানো দেখায়, কিন্তু setValue() বা postValue() বিভিন্ন কারণে mName আপডেট করার জন্য কল করা যেতে পারে, যার মধ্যে একটি নেটওয়ার্ক অনুরোধের প্রতিক্রিয়া বা একটি ডাটাবেস লোড সম্পূর্ণ হওয়া সহ; সব ক্ষেত্রে, setValue() বা postValue() এ কল পর্যবেক্ষকদের ট্রিগার করে এবং UI আপডেট করে।

রুমের সাথে লাইভডেটা ব্যবহার করুন

রুম পারসিসটেন্স লাইব্রেরি পর্যবেক্ষণযোগ্য প্রশ্নগুলিকে সমর্থন করে, যা LiveData অবজেক্ট ফেরত দেয়। পর্যবেক্ষণযোগ্য প্রশ্নগুলি একটি ডাটাবেস অ্যাক্সেস অবজেক্ট (DAO) এর অংশ হিসাবে লেখা হয়।

একটি ডাটাবেস আপডেট করা হলে রুমটি LiveData অবজেক্ট আপডেট করার জন্য সমস্ত প্রয়োজনীয় কোড তৈরি করে। উত্পন্ন কোড প্রয়োজন হলে একটি পটভূমি থ্রেডে অ্যাসিঙ্ক্রোনাসভাবে কোয়েরি চালায়। এই প্যাটার্নটি ডাটাবেসে সংরক্ষিত ডেটার সাথে সিঙ্কে একটি UI-তে প্রদর্শিত ডেটা রাখার জন্য দরকারী। আপনি রুম পারসিস্টেন্ট লাইব্রেরি গাইডে রুম এবং DAO সম্পর্কে আরও পড়তে পারেন।

লাইভডেটা দিয়ে কোরোটিন ব্যবহার করুন

LiveData কোটলিন কোরোটিনের জন্য সমর্থন অন্তর্ভুক্ত করে। আরও তথ্যের জন্য, অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলির সাথে কোটলিন কোরোটিন ব্যবহার করুন দেখুন।

একটি অ্যাপের আর্কিটেকচারে লাইভডেটা

LiveData হল লাইফসাইকেল-সচেতন, অ্যাক্টিভিটি এবং ফ্র্যাগমেন্টের মতো সত্তার জীবনচক্র অনুসরণ করে। এই লাইফসাইকেল মালিকদের এবং ViewModel অবজেক্টের মতো ভিন্ন জীবনকাল সহ অন্যান্য বস্তুর মধ্যে যোগাযোগ করতে LiveData ব্যবহার করুন। ViewModel প্রধান দায়িত্ব হল UI-সম্পর্কিত ডেটা লোড করা এবং পরিচালনা করা, যা এটিকে LiveData অবজেক্টগুলি ধরে রাখার জন্য একটি দুর্দান্ত প্রার্থী করে তোলে। ViewModelLiveData অবজেক্ট তৈরি করুন এবং UI স্তরে স্থিতি প্রকাশ করতে সেগুলি ব্যবহার করুন।

ক্রিয়াকলাপ এবং টুকরোগুলি LiveData দৃষ্টান্ত ধারণ করা উচিত নয় কারণ তাদের ভূমিকা হল ডেটা প্রদর্শন করা, স্থিতি রাখা নয়। এছাড়াও, ডেটা ধারণ করা থেকে ক্রিয়াকলাপ এবং টুকরোগুলিকে মুক্ত রাখা ইউনিট পরীক্ষা লেখা সহজ করে তোলে।

আপনার ডেটা লেয়ার ক্লাসে LiveData অবজেক্টগুলি কাজ করার জন্য এটি প্রলুব্ধ হতে পারে, তবে LiveData ডেটার অ্যাসিঙ্ক্রোনাস স্ট্রিমগুলি পরিচালনা করার জন্য ডিজাইন করা হয়নি। যদিও আপনি এটি অর্জন করতে LiveData রূপান্তর এবং MediatorLiveData ব্যবহার করতে পারেন, এই পদ্ধতির ত্রুটি রয়েছে: ডেটার স্ট্রিমগুলিকে একত্রিত করার ক্ষমতা খুবই সীমিত এবং সমস্ত LiveData অবজেক্টগুলি (পরিবর্তনের মাধ্যমে তৈরি করা সহ) প্রধান থ্রেডে পর্যবেক্ষণ করা হয়। নীচের কোডটি Repository একটি LiveData কীভাবে মূল থ্রেডটিকে ব্লক করতে পারে তার একটি উদাহরণ:

কোটলিন

class UserRepository {

    // DON'T DO THIS! LiveData objects should not live in the repository.
    fun getUsers(): LiveData<List<User>> {
        ...
    }

    fun getNewPremiumUsers(): LiveData<List<User>> {
        return getUsers().map { users ->
            // This is an expensive call being made on the main thread and may
            // cause noticeable jank in the UI!
            users
                .filter { user ->
                  user.isPremium
                }
          .filter { user ->
              val lastSyncedTime = dao.getLastSyncedTime()
              user.timeCreated > lastSyncedTime
                }
    }
}

জাভা

class UserRepository {

    // DON'T DO THIS! LiveData objects should not live in the repository.
    LiveData<List<User>> getUsers() {
        ...
    }

    LiveData<List<User>> getNewPremiumUsers() {
    return Transformations.map(getUsers(),
        // This is an expensive call being made on the main thread and may cause
        // noticeable jank in the UI!
        users -> users.stream()
            .filter(User::isPremium)
            .filter(user ->
                user.getTimeCreated() > dao.getLastSyncedTime())
            .collect(Collectors.toList()));
    }
}

আপনি যদি আপনার অ্যাপের অন্যান্য স্তরগুলিতে ডেটার স্ট্রীম ব্যবহার করতে চান, তাহলে Kotlin Flows ব্যবহার করার কথা বিবেচনা করুন এবং তারপর asLiveData() ব্যবহার করে ViewModel LiveData রূপান্তর করুন। এই কোডল্যাবে LiveData সহ কোটলিন Flow ব্যবহার সম্পর্কে আরও জানুন। জাভা দিয়ে তৈরি কোডবেসগুলির জন্য, কলব্যাক বা RxJava এর সাথে এক্সিকিউটর ব্যবহার করার কথা বিবেচনা করুন।

লাইভডেটা প্রসারিত করুন

লাইভডেটা একজন পর্যবেক্ষককে সক্রিয় অবস্থায় বিবেচনা করে যদি পর্যবেক্ষকের জীবনচক্র STARTED বা RESUMED অবস্থায় থাকে। নিম্নলিখিত নমুনা কোডটি ব্যাখ্যা করে কিভাবে LiveData ক্লাস প্রসারিত করা যায়:

কোটলিন

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }
}

জাভা

public class StockLiveData extends LiveData<BigDecimal> {
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    public StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}

এই উদাহরণে মূল্য শ্রোতার বাস্তবায়ন নিম্নলিখিত গুরুত্বপূর্ণ পদ্ধতিগুলি অন্তর্ভুক্ত করে:

  • onActive() পদ্ধতিটিকে বলা হয় যখন LiveData অবজেক্টের একটি সক্রিয় পর্যবেক্ষক থাকে। এর মানে আপনাকে এই পদ্ধতি থেকে স্টক মূল্য আপডেট পর্যবেক্ষণ শুরু করতে হবে।
  • onInactive() পদ্ধতিটি বলা হয় যখন LiveData অবজেক্টের কোনো সক্রিয় পর্যবেক্ষক না থাকে। যেহেতু কোন পর্যবেক্ষক শুনছেন না, StockManager পরিষেবার সাথে সংযুক্ত থাকার কোন কারণ নেই।
  • setValue(T) পদ্ধতি LiveData দৃষ্টান্তের মান আপডেট করে এবং যেকোনো সক্রিয় পর্যবেক্ষককে পরিবর্তন সম্পর্কে অবহিত করে।

আপনি নিম্নলিখিত হিসাবে StockLiveData ক্লাস ব্যবহার করতে পারেন:

কোটলিন

public class MyFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val myPriceListener: LiveData<BigDecimal> = ...
        myPriceListener.observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
            // Update the UI.
        })
    }
}

জাভা

public class MyFragment extends Fragment {
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(getViewLifecycleOwner(), price -> {
            // Update the UI.
        });
    }
}

observe() পদ্ধতিটি LifecycleOwner প্রথম আর্গুমেন্ট হিসাবে খণ্ডের দৃষ্টিভঙ্গির সাথে যুক্ত করে। এটি করা বোঝায় যে এই পর্যবেক্ষক মালিকের সাথে যুক্ত Lifecycle বস্তুর সাথে আবদ্ধ, অর্থ:

  • যদি Lifecycle বস্তুটি সক্রিয় অবস্থায় না থাকে, তাহলে মান পরিবর্তন হলেও পর্যবেক্ষককে ডাকা হয় না।
  • Lifecycle অবজেক্টটি ধ্বংস হওয়ার পরে, পর্যবেক্ষকটি স্বয়ংক্রিয়ভাবে সরানো হয়।

LiveData অবজেক্টগুলি জীবনচক্র-সচেতন হওয়ার অর্থ হল আপনি সেগুলিকে একাধিক ক্রিয়াকলাপ, টুকরো এবং পরিষেবাগুলির মধ্যে ভাগ করতে পারেন৷ উদাহরণটি সহজ রাখার জন্য, আপনি LiveData ক্লাসটিকে সিঙ্গলটন হিসাবে নিম্নরূপ প্রয়োগ করতে পারেন:

কোটলিন

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private val stockManager: StockManager = StockManager(symbol)

    private val listener = { price: BigDecimal ->
        value = price
    }

    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }

    companion object {
        private lateinit var sInstance: StockLiveData

        @MainThread
        fun get(symbol: String): StockLiveData {
            sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
            return sInstance
        }
    }
}

জাভা

public class StockLiveData extends LiveData<BigDecimal> {
    private static StockLiveData sInstance;
    private StockManager stockManager;

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            setValue(price);
        }
    };

    @MainThread
    public static StockLiveData get(String symbol) {
        if (sInstance == null) {
            sInstance = new StockLiveData(symbol);
        }
        return sInstance;
    }

    private StockLiveData(String symbol) {
        stockManager = new StockManager(symbol);
    }

    @Override
    protected void onActive() {
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        stockManager.removeUpdates(listener);
    }
}

এবং আপনি এটিকে নিম্নরূপ খণ্ডে ব্যবহার করতে পারেন:

কোটলিন

class MyFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
            // Update the UI.
        })

    }

জাভা

public class MyFragment extends Fragment {
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
            // Update the UI.
        });
    }
}

একাধিক খণ্ড এবং ক্রিয়াকলাপ MyPriceListener দৃষ্টান্ত পর্যবেক্ষণ করতে পারে। LiveData শুধুমাত্র সিস্টেম পরিষেবার সাথে সংযোগ করে যদি তাদের মধ্যে এক বা একাধিক দৃশ্যমান এবং সক্রিয় থাকে।

লাইভডেটা রূপান্তর করুন

আপনি একটি LiveData অবজেক্টে সংরক্ষিত মানটি পর্যবেক্ষকদের কাছে পাঠানোর আগে পরিবর্তন করতে চাইতে পারেন, অথবা অন্য একটির মানের উপর ভিত্তি করে আপনাকে একটি ভিন্ন LiveData উদাহরণ ফেরত দিতে হতে পারে। Lifecycle প্যাকেজ Transformations ক্লাস প্রদান করে যার মধ্যে সাহায্যকারী পদ্ধতি রয়েছে যা এই পরিস্থিতিতে সমর্থন করে।

Transformations.map()
LiveData অবজেক্টে সঞ্চিত মানের উপর একটি ফাংশন প্রয়োগ করে, এবং ফলাফলকে নিচের দিকে প্রচার করে।

কোটলিন

val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = userLiveData.map {
    user -> "${user.name} ${user.lastName}"
}

জাভা

LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});
Transformations.switchMap()
map() এর অনুরূপ, LiveData অবজেক্টে সঞ্চিত মানের জন্য একটি ফাংশন প্রয়োগ করে এবং ফলাফলটি ডাউনস্ট্রিমে আনর্যাপ করে এবং প্রেরণ করে। switchMap() এ পাস করা ফাংশনটি অবশ্যই একটি LiveData অবজেক্ট ফেরত দেবে, যেমনটি নিম্নলিখিত উদাহরণ দ্বারা চিত্রিত হয়েছে:

কোটলিন

private fun getUser(id: String): LiveData<User> {
  ...
}
val userId: LiveData<String> = ...
val user = userId.switchMap { id -> getUser(id) }

জাভা

private LiveData<User> getUser(String id) {
  ...;
}

LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

আপনি পর্যবেক্ষকের জীবনচক্র জুড়ে তথ্য বহন করতে রূপান্তর পদ্ধতি ব্যবহার করতে পারেন। রূপান্তরগুলি গণনা করা হয় না যদি না একজন পর্যবেক্ষক ফিরে আসা LiveData অবজেক্টটি দেখছেন। যেহেতু রূপান্তরগুলি অলসভাবে গণনা করা হয়, জীবনচক্র-সম্পর্কিত আচরণগুলি অতিরিক্ত স্পষ্ট কল বা নির্ভরতার প্রয়োজন ছাড়াই অন্তর্নিহিতভাবে পাস করা হয়।

আপনি যদি মনে করেন যে আপনার একটি ViewModel অবজেক্টের মধ্যে একটি Lifecycle অবজেক্টের প্রয়োজন, একটি রূপান্তর সম্ভবত একটি ভাল সমাধান। উদাহরণস্বরূপ, ধরে নিন যে আপনার কাছে একটি UI উপাদান রয়েছে যা একটি ঠিকানা গ্রহণ করে এবং সেই ঠিকানার জন্য পোস্টাল কোড ফেরত দেয়। আপনি নিম্নলিখিত নমুনা কোড দ্বারা চিত্রিত হিসাবে এই উপাদানের জন্য নিষ্পাপ ViewModel বাস্তবায়ন করতে পারেন:

কোটলিন

class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() {

    private fun getPostalCode(address: String): LiveData<String> {
        // DON'T DO THIS
        return repository.getPostCode(address)
    }
}

জাভা

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    public MyViewModel(PostalCodeRepository repository) {
       this.repository = repository;
    }

    private LiveData<String> getPostalCode(String address) {
       // DON'T DO THIS
       return repository.getPostCode(address);
    }
}

UI উপাদানটিকে তখন পূর্ববর্তী LiveData অবজেক্ট থেকে নিবন্ধনমুক্ত করতে হবে এবং প্রতিবার getPostalCode() কল করার সময় নতুন উদাহরণে নিবন্ধন করতে হবে। উপরন্তু, যদি UI উপাদানটি পুনরায় তৈরি করা হয়, এটি পূর্ববর্তী কলের ফলাফল ব্যবহার করার পরিবর্তে repository.getPostCode() পদ্ধতিতে আরেকটি কল ট্রিগার করে।

পরিবর্তে, আপনি ঠিকানা ইনপুটের একটি রূপান্তর হিসাবে পোস্টাল কোড লুকআপ বাস্তবায়ন করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

কোটলিন

class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() {
    private val addressInput = MutableLiveData<String>()
    val postalCode: LiveData<String> = addressInput.switchMap {
            address -> repository.getPostCode(address) }


    private fun setInput(address: String) {
        addressInput.value = address
    }
}

জাভা

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    private final MutableLiveData<String> addressInput = new MutableLiveData();
    public final LiveData<String> postalCode =
            Transformations.switchMap(addressInput, (address) -> {
                return repository.getPostCode(address);
             });

  public MyViewModel(PostalCodeRepository repository) {
      this.repository = repository
  }

  private void setInput(String address) {
      addressInput.setValue(address);
  }
}

এই ক্ষেত্রে, postalCode ক্ষেত্রটি addressInput এর রূপান্তর হিসাবে সংজ্ঞায়িত করা হয়। যতক্ষণ না আপনার অ্যাপে postalCode ক্ষেত্রের সাথে যুক্ত একজন সক্রিয় পর্যবেক্ষক থাকে, ততক্ষণ যখনই addressInput পরিবর্তন হয় তখন ক্ষেত্রের মান পুনরায় গণনা করা হয় এবং পুনরুদ্ধার করা হয়।

এই প্রক্রিয়াটি অ্যাপের নিম্ন স্তরের LiveData বস্তু তৈরি করতে দেয় যা অলসভাবে চাহিদা অনুযায়ী গণনা করা হয়। একটি ViewModel অবজেক্ট সহজেই LiveData অবজেক্টের রেফারেন্স পেতে পারে এবং তারপরে তাদের উপরে রূপান্তর নিয়ম সংজ্ঞায়িত করতে পারে।

নতুন রূপান্তর তৈরি করুন

আপনার অ্যাপে উপযোগী হতে পারে এমন এক ডজন ভিন্ন নির্দিষ্ট রূপান্তর আছে, কিন্তু সেগুলি ডিফল্টরূপে প্রদান করা হয় না। আপনার নিজের রূপান্তর বাস্তবায়নের জন্য আপনি MediatorLiveData ক্লাস ব্যবহার করতে পারেন, যা অন্যান্য LiveData অবজেক্টগুলি শোনে এবং তাদের দ্বারা নির্গত ইভেন্টগুলি প্রক্রিয়া করে। MediatorLiveData সঠিকভাবে তার স্থিতি উৎস LiveData অবজেক্টে প্রচার করে। এই প্যাটার্ন সম্পর্কে আরও জানতে, Transformations ক্লাসের রেফারেন্স ডকুমেন্টেশন দেখুন।

একাধিক LiveData উত্স একত্রিত করুন

MediatorLiveData হল LiveData এর একটি সাবক্লাস যা আপনাকে একাধিক LiveData উৎস একত্রিত করতে দেয়। MediatorLiveData অবজেক্টের পর্যবেক্ষকদের তখনই ট্রিগার করা হয় যখনই আসল লাইভডেটা সোর্স অবজেক্টের কোনো পরিবর্তন হয়।

উদাহরণস্বরূপ, যদি আপনার UI-তে একটি LiveData অবজেক্ট থাকে যা একটি স্থানীয় ডাটাবেস বা নেটওয়ার্ক থেকে আপডেট করা যেতে পারে, তাহলে আপনি নিম্নোক্ত উৎসগুলিকে MediatorLiveData অবজেক্টে যুক্ত করতে পারেন:

  • ডাটাবেসে সংরক্ষিত ডেটার সাথে যুক্ত একটি LiveData অবজেক্ট।
  • নেটওয়ার্ক থেকে অ্যাক্সেস করা ডেটার সাথে যুক্ত একটি LiveData অবজেক্ট।

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

অতিরিক্ত সম্পদ

LiveData ক্লাস সম্পর্কে আরও জানতে, নিম্নলিখিত সংস্থানগুলি দেখুন৷

নমুনা

কোডল্যাব

ব্লগ

ভিডিও

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}