Android Kotlin Fundamentals 05.2: LiveData এবং LiveData পর্যবেক্ষক

এই কোডল্যাবটি অ্যান্ড্রয়েড কোটলিন ফান্ডামেন্টাল কোর্সের অংশ। আপনি যদি ক্রমানুসারে কোডল্যাবগুলির মাধ্যমে কাজ করেন তবে আপনি এই কোর্সের সর্বাধিক মূল্য পাবেন৷ সমস্ত কোর্স কোডল্যাব অ্যান্ড্রয়েড কোটলিন ফান্ডামেন্টাল কোডল্যাব ল্যান্ডিং পৃষ্ঠায় তালিকাভুক্ত করা হয়েছে।

ভূমিকা

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

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

আপনি ইতিমধ্যে কি জানা উচিত

  • কোটলিনে কীভাবে বেসিক অ্যান্ড্রয়েড অ্যাপ তৈরি করবেন।
  • আপনার অ্যাপের গন্তব্যের মধ্যে কীভাবে নেভিগেট করবেন।
  • কার্যকলাপ এবং খণ্ড জীবনচক্র।
  • আপনার অ্যাপে ViewModel অবজেক্টগুলি কীভাবে ব্যবহার করবেন।
  • কিভাবে ViewModelProvider.Factory ইন্টারফেস ব্যবহার করে ViewModel অবজেক্ট তৈরি করবেন।

আপনি কি শিখবেন

  • কি LiveData বস্তু দরকারী করে তোলে.
  • ViewModel সংরক্ষিত ডেটাতে কীভাবে LiveData যুক্ত করবেন।
  • কখন এবং কিভাবে MutableLiveData ব্যবহার করবেন।
  • LiveData.
  • একটি ব্যাকিং সম্পত্তি ব্যবহার করে কিভাবে LiveData এনক্যাপসুলেট করবেন।
  • কিভাবে একটি UI কন্ট্রোলার এবং এর সংশ্লিষ্ট ViewModel এর মধ্যে যোগাযোগ করতে হয়।

আপনি কি করবেন

  • GuessTheWord অ্যাপে শব্দ এবং স্কোরের জন্য LiveData ব্যবহার করুন।
  • শব্দ বা স্কোর পরিবর্তিত হলে লক্ষ্য করে এমন পর্যবেক্ষকদের যোগ করুন।
  • পরিবর্তিত মানগুলি প্রদর্শন করে এমন পাঠ্য দৃশ্যগুলি আপডেট করুন।
  • একটি গেম-সমাপ্ত ইভেন্ট যোগ করতে LiveData পর্যবেক্ষক প্যাটার্ন ব্যবহার করুন।
  • আবার প্লে বোতামটি প্রয়োগ করুন।

পাঠ 5 কোডল্যাবগুলিতে, আপনি স্টার্টার কোড দিয়ে শুরু করে GuessTheWord অ্যাপ তৈরি করেন। GuessTheWord হল একটি দুই-প্লেয়ার চ্যারেড -স্টাইলের খেলা, যেখানে খেলোয়াড়রা সম্ভাব্য সর্বোচ্চ স্কোর অর্জন করতে সহযোগিতা করে।

প্রথম প্লেয়ার অ্যাপে থাকা শব্দগুলি দেখে এবং পালাক্রমে প্রতিটি কাজ করে, নিশ্চিত করে যে শব্দটি দ্বিতীয় প্লেয়ারকে না দেখায়৷ দ্বিতীয় খেলোয়াড় শব্দটি অনুমান করার চেষ্টা করে।

গেমটি খেলতে, প্রথম প্লেয়ার ডিভাইসে অ্যাপটি খোলে এবং একটি শব্দ দেখতে পায়, উদাহরণস্বরূপ "গিটার", যেমনটি নীচের স্ক্রিনশটে দেখানো হয়েছে৷

প্রথম খেলোয়াড় শব্দটি কার্যকর করে, সতর্কতা অবলম্বন করে যে শব্দটি নিজেই না বলে।

  • যখন দ্বিতীয় প্লেয়ার সঠিকভাবে শব্দটি অনুমান করে, প্রথম প্লেয়ার Got It বোতাম টিপে, যা এক দ্বারা গণনা বৃদ্ধি করে এবং পরবর্তী শব্দটি দেখায়।
  • যদি দ্বিতীয় প্লেয়ার শব্দটি অনুমান করতে না পারে, প্রথম খেলোয়াড় স্কিপ বোতাম টিপে, যা গণনা এক দ্বারা হ্রাস করে এবং পরবর্তী শব্দে চলে যায়।
  • গেমটি শেষ করতে, এন্ড গেম বোতাম টিপুন। (এই কার্যকারিতা সিরিজের প্রথম কোডল্যাবের জন্য স্টার্টার কোডে নেই।)

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

শিরোনাম পর্দা

খেলা পর্দা

স্কোর স্ক্রীন

এই কাজটিতে, আপনি এই কোডল্যাবের জন্য আপনার স্টার্টার কোডটি সনাক্ত করুন এবং চালান। আপনি আপনার স্টার্টার কোড হিসাবে পূর্ববর্তী কোডল্যাবে তৈরি করা GuessTheWord অ্যাপটি ব্যবহার করতে পারেন, অথবা আপনি একটি স্টার্টার অ্যাপ ডাউনলোড করতে পারেন।

  1. (ঐচ্ছিক) আপনি যদি আগের কোডল্যাব থেকে আপনার কোড ব্যবহার না করে থাকেন, তাহলে এই কোডল্যাবের জন্য স্টার্টার কোডটি ডাউনলোড করুন । কোডটি আনজিপ করুন এবং অ্যান্ড্রয়েড স্টুডিওতে প্রকল্পটি খুলুন।
  2. অ্যাপটি চালান এবং গেমটি খেলুন।
  3. লক্ষ্য করুন যে Skip বোতামটি পরবর্তী শব্দটি প্রদর্শন করে এবং একটি দ্বারা স্কোর হ্রাস করে এবং Got It বোতামটি পরবর্তী শব্দটি দেখায় এবং একটি দ্বারা স্কোর বৃদ্ধি করে। এন্ড গেম বোতামটি গেমটি শেষ করে।

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

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

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

ধাপ 1: LiveData ব্যবহার করতে স্কোর এবং শব্দ পরিবর্তন করুন

  1. screens/game প্যাকেজের অধীনে, GameViewModel ফাইলটি খুলুন।
  2. পরিবর্তনশীল score এবং word ধরন পরিবর্তন করে MutableLiveData

    MutableLiveData হল একটি LiveData যার মান পরিবর্তন করা যায়। MutableLiveData হল একটি জেনেরিক ক্লাস, তাই আপনাকে এটিতে থাকা ডেটার ধরন নির্দিষ্ট করতে হবে।
// The current word
val word = MutableLiveData<String>()
// The current score
val score = MutableLiveData<Int>()
  1. GameViewModel এ, init ব্লকের ভিতরে, score এবং word শুরু করুন। একটি LiveData ভেরিয়েবলের মান পরিবর্তন করতে, আপনি ভেরিয়েবলে setValue() পদ্ধতি ব্যবহার করেন। কোটলিনে, আপনি value সম্পত্তি ব্যবহার করে setValue() কল করতে পারেন।
init {

   word.value = ""
   score.value = 0
  ...
}

ধাপ 2: LiveData অবজেক্ট রেফারেন্স আপডেট করুন

score এবং word ভেরিয়েবল এখন LiveData ধরনের। এই ধাপে, আপনি value সম্পত্তি ব্যবহার করে এই ভেরিয়েবলের রেফারেন্স পরিবর্তন করুন।

  1. GameViewModel এ, onSkip() পদ্ধতিতে, score পরিবর্তন করে score.valuescore সম্ভবত null হওয়ার বিষয়ে ত্রুটিটি লক্ষ্য করুন। আপনি পরবর্তী এই ত্রুটি ঠিক করুন.
  2. ত্রুটিটি সমাধান করতে, onSkip()score.value এ একটি null চেক যোগ করুন। তারপর score minus() ফাংশন কল করুন, যা null -safety সহ বিয়োগ সম্পাদন করে।
fun onSkip() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.minus(1)
   }
   nextWord()
}
  1. onCorrect() পদ্ধতিটি আপডেট করুন: score ভেরিয়েবলে একটি null চেক যুক্ত করুন এবং plus() ফাংশনটি ব্যবহার করুন।
fun onCorrect() {
   if (!wordList.isEmpty()) {
       score.value = (score.value)?.plus(1)
   }
   nextWord()
}
  1. GameViewModel এ, nextWord() পদ্ধতির ভিতরে, word রেফারেন্স word পরিবর্তন করুন . value
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       word.value = wordList.removeAt(0)
   }
}
  1. GameFragment এ, updateWordText() পদ্ধতির ভিতরে, viewModel .word থেকে viewModel এ রেফারেন্স পরিবর্তন করুন . word . value.
/** Methods for updating the UI **/
private fun updateWordText() {
   binding.wordText.text = viewModel.word.value
}
  1. GameFragment এ, updateScoreText() পদ্ধতির ভিতরে, viewModel .score এর রেফারেন্স পরিবর্তন করে viewModel করুন . score . value.
private fun updateScoreText() {
   binding.scoreText.text = viewModel.score.value.toString()
}
  1. GameFragment এ, gameFinished() পদ্ধতির ভিতরে, viewModel .score এ রেফারেন্স পরিবর্তন করে viewModel করুন . score . value প্রয়োজনীয় null -সেফটি চেক যোগ করুন।
private fun gameFinished() {
   Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
   val action = GameFragmentDirections.actionGameToScore()
   action.score = viewModel.score.value?:0
   NavHostFragment.findNavController(this).navigate(action)
}
  1. আপনার কোডে কোন ত্রুটি আছে তা নিশ্চিত করুন। কম্পাইল এবং আপনার অ্যাপ্লিকেশন চালান. অ্যাপটির কার্যকারিতা আগের মতোই হওয়া উচিত।

এই টাস্কটি আগের টাস্কের সাথে ঘনিষ্ঠভাবে সম্পর্কিত, যেখানে আপনি স্কোর এবং শব্দ ডেটাকে LiveData অবজেক্টে রূপান্তর করেছেন। এই টাস্কে, আপনি সেই LiveData অবজেক্টের সাথে Observer অবজেক্ট সংযুক্ত করুন।

  1. GameFragment, onCreateView() পদ্ধতির ভিতরে, বর্তমান স্কোর, viewModel.score এর জন্য LiveData অবজেক্টের সাথে একটি Observer অবজেক্ট সংযুক্ত করুন। observe() পদ্ধতিটি ব্যবহার করুন এবং viewModel এর আরম্ভ করার পরে কোডটি রাখুন। কোডটি সরল করতে একটি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করুন। (একটি ল্যাম্বডা এক্সপ্রেশন একটি বেনামী ফাংশন যা ঘোষণা করা হয় না, তবে একটি অভিব্যক্তি হিসাবে অবিলম্বে পাস করা হয়।)
viewModel.score.observe(this, Observer { newScore ->
})

Observer রেফারেন্সটি সমাধান করুন। এটি করার জন্য, Observer এ ক্লিক করুন, Alt+Enter ( Mac-এ Option+Enter ), এবং androidx.lifecycle.Observer আমদানি করুন।

  1. আপনি যে পর্যবেক্ষকটি এইমাত্র তৈরি করেছেন সেটি একটি ইভেন্ট গ্রহণ করে যখন পর্যবেক্ষণ করা LiveData অবজেক্ট দ্বারা ধারণকৃত ডেটা পরিবর্তিত হয়। পর্যবেক্ষকের ভিতরে, নতুন স্কোর সহ TextView স্কোর আপডেট করুন।
/** Setting up LiveData observation relationship **/
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})
  1. বর্তমান শব্দ LiveData অবজেক্টের সাথে একটি Observer বস্তু সংযুক্ত করুন। আপনি বর্তমান স্কোরের সাথে একটি Observer বস্তু সংযুক্ত করেছেন একইভাবে এটি করুন।
/** Setting up LiveData observation relationship **/
viewModel.word.observe(this, Observer { newWord ->
   binding.wordText.text = newWord
})

যখন score বা word মান পরিবর্তিত হয়, তখন স্ক্রিনে প্রদর্শিত score বা word এখন স্বয়ংক্রিয়ভাবে আপডেট হয়।

  1. GameFragment এ, updateWordText() এবং updateScoreText() ) পদ্ধতি এবং সেগুলির সমস্ত রেফারেন্স মুছে দিন। আপনার আর এগুলোর প্রয়োজন নেই, কারণ টেক্সট ভিউ LiveData পর্যবেক্ষক পদ্ধতি দ্বারা আপডেট করা হয়।
  2. আপনার অ্যাপ চালান। আপনার গেম অ্যাপটি ঠিক আগের মতোই কাজ করা উচিত, কিন্তু এখন এটি LiveData এবং LiveData পর্যবেক্ষক ব্যবহার করে।

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

আপনার বর্তমান কোডে, যেকোনো বাহ্যিক শ্রেণী value বৈশিষ্ট্য ব্যবহার করে score এবং word ভেরিয়েবল পরিবর্তন করতে পারে, উদাহরণস্বরূপ viewModel.score.value ব্যবহার করে। আপনি এই কোডল্যাবে যে অ্যাপটি ডেভেলপ করছেন তাতে কিছু যায় আসে না, কিন্তু একটি প্রোডাকশন অ্যাপে, আপনি ViewModel অবজেক্টের ডেটার উপর নিয়ন্ত্রণ চান।

শুধুমাত্র ViewModel আপনার অ্যাপের ডেটা সম্পাদনা করবে। কিন্তু UI কন্ট্রোলারদের ডেটা পড়তে হবে, তাই ডেটা ক্ষেত্রগুলি সম্পূর্ণ ব্যক্তিগত হতে পারে না। আপনার অ্যাপের ডেটা এনক্যাপসুলেট করতে, আপনি MutableLiveData এবং LiveData অবজেক্ট উভয়ই ব্যবহার করেন।

MutableLiveData বনাম LiveData :

  • একটি MutableLiveData অবজেক্টের ডেটা পরিবর্তন করা যেতে পারে, যেমন নামটি বোঝায়। ViewModel এর ভিতরে, ডেটা সম্পাদনাযোগ্য হওয়া উচিত, তাই এটি MutableLiveData ব্যবহার করে।
  • একটি LiveData অবজেক্টের ডেটা পড়া যায়, কিন্তু পরিবর্তন করা যায় না। ViewModel এর বাইরে থেকে, ডেটা পাঠযোগ্য হওয়া উচিত, কিন্তু সম্পাদনাযোগ্য নয়, তাই ডেটা LiveData হিসাবে প্রকাশ করা উচিত।

এই কৌশলটি চালানোর জন্য, আপনি একটি Kotlin ব্যাকিং সম্পত্তি ব্যবহার করুন। একটি ব্যাকিং প্রপার্টি আপনাকে সঠিক বস্তু ব্যতীত অন্য গেটার থেকে কিছু ফেরত দিতে দেয়। এই কাজটিতে, আপনি GuessTheWord অ্যাপে score এবং word বস্তুর জন্য একটি ব্যাকিং প্রপার্টি প্রয়োগ করেন।

স্কোর এবং শব্দে একটি ব্যাকিং সম্পত্তি যোগ করুন

  1. GameViewModel এ, বর্তমান score অবজেক্টটিকে private করুন।
  2. ব্যাকিং বৈশিষ্ট্যে ব্যবহৃত নামকরণের নিয়ম অনুসরণ করতে, score _score এ পরিবর্তন করুন। _score সম্পত্তিটি এখন গেম স্কোরের পরিবর্তনযোগ্য সংস্করণ, যা অভ্যন্তরীণভাবে ব্যবহার করা হবে।
  3. LiveData প্রকারের একটি সর্বজনীন সংস্করণ তৈরি করুন, যাকে বলা হয় score
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
  1. আপনি একটি আরম্ভ ত্রুটি দেখতে. এই ত্রুটিটি ঘটে কারণ GameFragment ভিতরে, score একটি LiveData রেফারেন্স, এবং score আর এটির সেটার অ্যাক্সেস করতে পারে না। কোটলিনে গেটার এবং সেটার্স সম্পর্কে আরও জানতে, গেটার এবং সেটার্স দেখুন।

    ত্রুটিটি সমাধান করতে, GameViewModelscore অবজেক্টের জন্য get() পদ্ধতিটি ওভাররাইড করুন এবং ব্যাকিং প্রপার্টি, _score
val score: LiveData<Int>
   get() = _score
  1. GameViewModel এ, score রেফারেন্সগুলি এর অভ্যন্তরীণ পরিবর্তনযোগ্য সংস্করণে পরিবর্তন করুন, _score
init {
   ...
   _score.value = 0
   ...
}

...
fun onSkip() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.minus(1)
   }
  ...
}

fun onCorrect() {
   if (!wordList.isEmpty()) {
       _score.value = (score.value)?.plus(1)
   }
   ...
}
  1. word অবজেক্টের নাম পরিবর্তন করে _word করুন এবং এর জন্য একটি ব্যাকিং প্রপার্টি যোগ করুন, যেমন আপনি score অবজেক্টের জন্য করেছিলেন।
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
   get() = _word
...
init {
   _word.value = ""
   ...
}
...
private fun nextWord() {
   if (!wordList.isEmpty()) {
       //Select and remove a word from the list
       _word.value = wordList.removeAt(0)
   }
}

দুর্দান্ত কাজ, আপনি LiveData অবজেক্টের word এবং score এনক্যাপসুলেট করেছেন।

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

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

পর্যবেক্ষক প্যাটার্ন

পর্যবেক্ষক প্যাটার্ন হল একটি সফটওয়্যার ডিজাইন প্যাটার্ন। এটি বস্তুর মধ্যে যোগাযোগ নির্দিষ্ট করে: একটি পর্যবেক্ষণযোগ্য (পর্যবেক্ষণের "বিষয়") এবং পর্যবেক্ষক । একটি পর্যবেক্ষণযোগ্য একটি বস্তু যা তার অবস্থার পরিবর্তন সম্পর্কে পর্যবেক্ষকদের অবহিত করে।

এই অ্যাপে LiveData এর ক্ষেত্রে, পর্যবেক্ষণযোগ্য (বিষয়) হল LiveData অবজেক্ট, এবং পর্যবেক্ষক হল UI কন্ট্রোলারের পদ্ধতি, যেমন টুকরা। যখনই LiveData এর ভিতরে মোড়ানো ডেটা পরিবর্তিত হয় তখনই একটি রাজ্যের পরিবর্তন ঘটে। ViewModel থেকে টুকরোতে যোগাযোগ করার জন্য LiveData ক্লাসগুলি অত্যন্ত গুরুত্বপূর্ণ৷

ধাপ 1: একটি গেম-সমাপ্ত ইভেন্ট সনাক্ত করতে LiveData ব্যবহার করুন

এই টাস্কে, আপনি একটি গেম-সমাপ্ত ইভেন্ট মডেল করতে LiveData পর্যবেক্ষক প্যাটার্ন ব্যবহার করেন।

  1. GameViewModel এ, _eventGameFinish নামে একটি Boolean MutableLiveData _eventGameFinish তৈরি করুন। এই বস্তুটি গেম-সমাপ্ত ইভেন্টটি ধরে রাখবে।
  2. _eventGameFinish অবজেক্ট আরম্ভ করার পরে, eventGameFinish নামে একটি ব্যাকিং প্রপার্টি তৈরি করুন এবং আরম্ভ করুন।
// Event which triggers the end of the game
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish: LiveData<Boolean>
   get() = _eventGameFinish
  1. GameViewModel এ, একটি onGameFinish() পদ্ধতি যোগ করুন। পদ্ধতিতে, গেম-সমাপ্ত ইভেন্ট, eventGameFinish , true সেট করুন।
/** Method for the game completed event **/
fun onGameFinish() {
   _eventGameFinish.value = true
}
  1. GameViewModel এ, nextWord() পদ্ধতির ভিতরে, শব্দ তালিকা খালি থাকলে গেমটি শেষ করুন।
private fun nextWord() {
   if (wordList.isEmpty()) {
       onGameFinish()
   } else {
       //Select and remove a _word from the list
       _word.value = wordList.removeAt(0)
   }
}
  1. GameFragment এ, onCreateView onCreateView() -এর ভিতরে, viewModel শুরু করার পর, viewModel এ একজন পর্যবেক্ষক সংযুক্ত eventGameFinishobserve() পদ্ধতি ব্যবহার করুন। ল্যাম্বডা ফাংশনের ভিতরে, gameFinished() পদ্ধতিতে কল করুন।
// Observer for the Game finished event
viewModel.eventGameFinish.observe(this, Observer<Boolean> { hasFinished ->
   if (hasFinished) gameFinished()
})
  1. আপনার অ্যাপ চালান, গেম খেলুন এবং সমস্ত শব্দের মধ্য দিয়ে যান। আপনি End Game এ ট্যাপ না করা পর্যন্ত গেমের অংশে থাকার পরিবর্তে অ্যাপটি স্বয়ংক্রিয়ভাবে স্কোর স্ক্রিনে নেভিগেট করে।

    শব্দ তালিকা খালি হওয়ার পরে, eventGameFinish সেট করা হয়, গেমের খণ্ডে সংশ্লিষ্ট পর্যবেক্ষক পদ্ধতিকে কল করা হয় এবং অ্যাপটি স্ক্রিন ফ্র্যাগমেন্টে নেভিগেট করে।
  2. আপনার যোগ করা কোড একটি জীবনচক্র সমস্যা চালু করেছে। সমস্যাটি বুঝতে, GameFragment ক্লাসে, gameFinished() পদ্ধতিতে নেভিগেশন কোডটি মন্তব্য করুন। পদ্ধতিতে Toast বার্তা রাখতে ভুলবেন না।
private fun gameFinished() {
       Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
//        val action = GameFragmentDirections.actionGameToScore()
//        action.score = viewModel.score.value?:0
//        NavHostFragment.findNavController(this).navigate(action)
   }
  1. আপনার অ্যাপ চালান, গেম খেলুন এবং সমস্ত শব্দের মধ্য দিয়ে যান। একটি টোস্ট বার্তা যা বলে "গেম সবে শেষ হয়েছে" গেম স্ক্রিনের নীচে সংক্ষেপে প্রদর্শিত হবে, যা প্রত্যাশিত আচরণ।

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

ধাপ 2: গেম-সমাপ্ত ইভেন্ট রিসেট করুন

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

এই কারণেই আপনার অ্যাপে গেম-সমাপ্ত টোস্ট বারবার ট্রিগার হয়। যখন স্ক্রীন ঘূর্ণনের পরে গেমের খণ্ডটি পুনরায় তৈরি করা হয়, তখন এটি একটি নিষ্ক্রিয় থেকে একটি সক্রিয় অবস্থায় চলে যায়। খণ্ডের পর্যবেক্ষক বিদ্যমান ViewModel সাথে পুনরায় সংযুক্ত হয় এবং বর্তমান ডেটা গ্রহণ করে। gameFinished() পদ্ধতিটি পুনরায় ট্রিগার করা হয় এবং টোস্ট প্রদর্শন করা হয়।

এই টাস্কে, আপনি এই সমস্যাটি ঠিক করুন এবং GameViewModeleventGameFinish পতাকা রিসেট করে শুধুমাত্র একবার টোস্ট প্রদর্শন করুন।

  1. GameViewModel এ, গেম সমাপ্ত ইভেন্ট, _eventGameFinish রিসেট করতে একটি onGameFinishComplete() পদ্ধতি যোগ করুন।
/** Method for the game completed event **/

fun onGameFinishComplete() {
   _eventGameFinish.value = false
}
  1. GameFragment এ, gameFinished() এর শেষে, viewModel অবজেক্টে onGameFinishComplete() কল করুন। ( gameFinished() এ নেভিগেশন কোড ছেড়ে দিন এখনের জন্য মন্তব্য করা হয়েছে।)
private fun gameFinished() {
   ...
   viewModel.onGameFinishComplete()
}
  1. অ্যাপটি চালান এবং গেমটি খেলুন। সমস্ত শব্দের মধ্য দিয়ে যান, তারপর ডিভাইসের পর্দার অভিযোজন পরিবর্তন করুন। টোস্ট শুধুমাত্র একবার প্রদর্শিত হয়.
  2. GameFragment এ, gameFinished() পদ্ধতির ভিতরে, নেভিগেশন কোডটি আনকমেন্ট করুন।

    অ্যান্ড্রয়েড স্টুডিওতে মন্তব্য করার জন্য, মন্তব্য করা লাইনগুলি নির্বাচন করুন এবং Control+/ ( একটি ম্যাকে Command+/ ) টিপুন।
private fun gameFinished() {
   Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
   val action = GameFragmentDirections.actionGameToScore()
   action.score = viewModel.score.value?:0
   findNavController(this).navigate(action)
   viewModel.onGameFinishComplete()
}

Android Studio দ্বারা অনুরোধ করা হলে, androidx.navigation.fragment.NavHostFragment.findNavController আমদানি করুন।

  1. অ্যাপটি চালান এবং গেমটি খেলুন। আপনি সমস্ত শব্দের মধ্য দিয়ে যাওয়ার পরে অ্যাপটি চূড়ান্ত স্কোর স্ক্রিনে স্বয়ংক্রিয়ভাবে নেভিগেট করে তা নিশ্চিত করুন।

দারূন কাজ! আপনার অ্যাপটি গেম-সমাপ্ত ইভেন্টকে ট্রিগার করতে LiveData থেকে গেমের GameViewModel যোগাযোগ করতে LiveData ব্যবহার করে যে শব্দ তালিকাটি খালি রয়েছে। গেমের খণ্ডটি তারপর স্কোর খণ্ডে নেভিগেট করে।

এই টাস্কে, আপনি ScoreViewModel এ একটি LiveData অবজেক্টে স্কোর পরিবর্তন করুন এবং এতে একজন পর্যবেক্ষক সংযুক্ত করুন। আপনি যখন LiveDataGameViewModel যোগ করেছিলেন তখন আপনি যা করেছিলেন এই কাজটি একই রকম।

আপনি সম্পূর্ণতার জন্য ScoreViewModel এ এই পরিবর্তনগুলি করেন, যাতে আপনার অ্যাপের সমস্ত ডেটা LiveData ব্যবহার করে।

  1. ScoreViewModel এ, score ভেরিয়েবলের ধরনটিকে MutableLiveData এ পরিবর্তন করুন। _score এ এটির নাম পরিবর্তন করুন এবং একটি ব্যাকিং প্রপার্টি যোগ করুন।
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
   get() = _score
  1. ScoreViewModel এ, init ব্লকের ভিতরে, _score শুরু করুন। আপনি আপনার পছন্দ মতো init ব্লকে লগটি সরাতে বা ছেড়ে দিতে পারেন।
init {
   _score.value = finalScore
}
  1. ScoreFragment এ, onCreateView onCreateView() এর ভিতরে, viewModel শুরু করার পর, স্কোর LiveData অবজেক্টের জন্য একজন পর্যবেক্ষক সংযুক্ত করুন। ল্যাম্বডা এক্সপ্রেশনের ভিতরে, স্কোর টেক্সট ভিউতে স্কোর মান সেট করুন। ViewModel থেকে স্কোর মান সহ পাঠ্য দৃশ্যকে সরাসরি বরাদ্দ করে এমন কোডটি সরান।

যোগ করার জন্য কোড:

// Add observer for score
viewModel.score.observe(this, Observer { newScore ->
   binding.scoreText.text = newScore.toString()
})

সরানোর জন্য কোড:

binding.scoreText.text = viewModel.score.toString()

Android Studio দ্বারা অনুরোধ করা হলে, androidx.lifecycle.Observer আমদানি করুন।

  1. আপনার অ্যাপটি চালান এবং গেমটি খেলুন। অ্যাপটি আগের মতো কাজ করা উচিত, কিন্তু এখন এটি স্কোর আপডেট করতে LiveData এবং একজন পর্যবেক্ষক ব্যবহার করে।

এই টাস্কে, আপনি স্কোর স্ক্রিনে একটি প্লে এগেইন বোতাম যোগ করুন এবং একটি LiveData ইভেন্ট ব্যবহার করে এটির ক্লিক শ্রোতাকে প্রয়োগ করুন। বোতামটি স্কোর স্ক্রীন থেকে গেম স্ক্রিনে নেভিগেট করার জন্য একটি ইভেন্টকে ট্রিগার করে।

অ্যাপের জন্য স্টার্টার কোডে প্লে এগেইন বোতাম রয়েছে, কিন্তু বোতামটি লুকানো আছে।

  1. res/layout/score_fragment.xml এ, play_again_button বোতামের জন্য, visibility বৈশিষ্ট্যের মান visible পরিবর্তন করুন।
<Button
   android:id="@+id/play_again_button"
...
   android:visibility="visible"
 />
  1. ScoreViewModel এ, _eventPlayAgain নামক Boolean ধরে রাখতে একটি LiveData অবজেক্ট যোগ করুন। স্কোর স্ক্রীন থেকে গেম স্ক্রিনে নেভিগেট করতে LiveData ইভেন্ট সংরক্ষণ করতে এই বস্তুটি ব্যবহার করা হয়।
private val _eventPlayAgain = MutableLiveData<Boolean>()
val eventPlayAgain: LiveData<Boolean>
   get() = _eventPlayAgain
  1. ScoreViewModel এ, ইভেন্ট সেট এবং রিসেট করার পদ্ধতি সংজ্ঞায়িত করুন, _eventPlayAgain
fun onPlayAgain() {
   _eventPlayAgain.value = true
}
fun onPlayAgainComplete() {
   _eventPlayAgain.value = false
}
  1. ScoreFragment , eventPlayAgain জন্য একজন পর্যবেক্ষক যোগ করুন। return স্টেটমেন্টের আগে onCreateView() এর শেষে কোডটি রাখুন। ল্যাম্বডা এক্সপ্রেশনের ভিতরে, গেম স্ক্রিনে ফিরে যান এবং eventPlayAgain রিসেট করুন।
// Navigates back to game when button is pressed
viewModel.eventPlayAgain.observe(this, Observer { playAgain ->
   if (playAgain) {
      findNavController().navigate(ScoreFragmentDirections.actionRestart())
       viewModel.onPlayAgainComplete()
   }
})

androidx.navigation.fragment.findNavController আমদানি করুন, যখন Android Studio দ্বারা প্রম্পট করা হবে।

  1. ScoreFragment এ, onCreateView onCreateView() এর ভিতরে, PlayAgain বোতামে একটি ক্লিক শ্রোতা যোগ করুন এবং viewModel .onPlayAgain() কল করুন।
binding.playAgainButton.setOnClickListener {  viewModel.onPlayAgain()  }
  1. আপনার অ্যাপটি চালান এবং গেমটি খেলুন। গেমটি শেষ হয়ে গেলে, স্কোর স্ক্রীন চূড়ান্ত স্কোর এবং আবার প্লে বোতামটি দেখায়। PlayAgain বোতামটি আলতো চাপুন, এবং অ্যাপটি গেম স্ক্রিনে নেভিগেট করে যাতে আপনি আবার গেমটি খেলতে পারেন।

ভাল কাজ! আপনি ViewModel-এ LiveData অবজেক্ট ব্যবহার করতে আপনার অ্যাপের আর্কিটেকচার পরিবর্তন করেছেন এবং আপনি ViewModel অবজেক্টের সাথে পর্যবেক্ষকদের সংযুক্ত LiveDataLiveData দ্বারা ধারণকৃত মান পরিবর্তিত হলে LiveData পর্যবেক্ষক বস্তুকে অবহিত করে।

অ্যান্ড্রয়েড স্টুডিও প্রকল্প: GuessTheWord

লাইভডেটা

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

LiveData যোগ করতে

  • ViewModel এ ডেটা ভেরিয়েবলের ধরন LiveData বা MutableLiveData এ পরিবর্তন করুন।

MutableLiveData হল একটি LiveData অবজেক্ট যার মান পরিবর্তন করা যায়। MutableLiveData হল একটি জেনেরিক ক্লাস, তাই আপনাকে এটিতে থাকা ডেটার ধরন নির্দিষ্ট করতে হবে।

  • LiveData দ্বারা ধারণকৃত ডেটার মান পরিবর্তন করতে, LiveData ভেরিয়েবলে setValue() পদ্ধতি ব্যবহার করুন।

LiveData encapsulate করতে

  • LiveData এর ভিতরে থাকা ViewModel সম্পাদনাযোগ্য হওয়া উচিত। ViewModel এর বাইরে, ViewModel পাঠযোগ্য LiveData উচিত। এটি একটি Kotlin ব্যাকিং সম্পত্তি ব্যবহার করে প্রয়োগ করা যেতে পারে।
  • একটি কোটলিন ব্যাকিং প্রপার্টি আপনাকে সঠিক বস্তু ব্যতীত অন্য কোনো গেটার থেকে কিছু ফেরত দিতে দেয়।
  • LiveData এনক্যাপসুলেট করতে, ViewModel-এর ভিতরে private MutableLiveData ব্যবহার করুন এবং ViewModel এর বাইরে একটি LiveData ব্যাকিং প্রপার্টি ViewModel

পর্যবেক্ষণযোগ্য লাইভডেটা

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

উদাসীনতা কোর্স:

অ্যান্ড্রয়েড ডেভেলপার ডকুমেন্টেশন:

অন্যান্য:

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

  • প্রয়োজনে হোমওয়ার্ক বরাদ্দ করুন।
  • শিক্ষার্থীদের সাথে যোগাযোগ করুন কিভাবে হোমওয়ার্ক অ্যাসাইনমেন্ট জমা দিতে হয়।
  • হোমওয়ার্ক অ্যাসাইনমেন্ট গ্রেড.

প্রশিক্ষকরা এই পরামর্শগুলি যতটা কম বা যতটা চান ততটা ব্যবহার করতে পারেন, এবং তাদের উপযুক্ত মনে করে অন্য কোনও হোমওয়ার্ক বরাদ্দ করতে নির্দ্বিধায় করা উচিত।

আপনি যদি এই কোডল্যাবের মাধ্যমে নিজে থেকে কাজ করে থাকেন, তাহলে আপনার জ্ঞান পরীক্ষা করার জন্য এই হোমওয়ার্ক অ্যাসাইনমেন্টগুলি ব্যবহার করুন।

এই প্রশ্নগুলোর উত্তর দাও

প্রশ্ন 1

আপনি কীভাবে একটি LiveData সংরক্ষিত ViewModel এনক্যাপসুলেট করবেন যাতে বাহ্যিক বস্তুগুলি আপডেট না করেই ডেটা পড়তে পারে?

  • ViewModel অবজেক্টের ভিতরে, ডেটার ডেটা টাইপকে private LiveData পরিবর্তন করুন। MutableLiveData প্রকারের শুধুমাত্র পঠনযোগ্য ডেটা প্রকাশ করতে একটি ব্যাকিং সম্পত্তি ব্যবহার করুন।
  • ViewModel অবজেক্টের ভিতরে, ডেটার ডেটা টাইপকে private MutableLiveData এ পরিবর্তন করুন। LiveData প্রকারের শুধুমাত্র পঠনযোগ্য ডেটা প্রকাশ করতে একটি ব্যাকিং সম্পত্তি ব্যবহার করুন।
  • UI কন্ট্রোলারের ভিতরে, ডেটার ডেটা প্রকারকে private MutableLiveData এ পরিবর্তন করুন। LiveData প্রকারের শুধুমাত্র পঠনযোগ্য ডেটা প্রকাশ করতে একটি ব্যাকিং সম্পত্তি ব্যবহার করুন।
  • ViewModel অবজেক্টের ভিতরে, ডাটার ডাটা টাইপকে LiveData এ পরিবর্তন করুন। LiveData প্রকারের শুধুমাত্র পঠনযোগ্য ডেটা প্রকাশ করতে একটি ব্যাকিং সম্পত্তি ব্যবহার করুন।

প্রশ্ন 2

UI কন্ট্রোলার নিচের কোন LiveData একটি UI কন্ট্রোলার (যেমন একটি খণ্ড) আপডেট করে?

  • আবার শুরু হয়েছে
  • পটভূমিতে
  • বিরতি দেওয়া হয়েছে
  • বন্ধ

প্রশ্ন 3

LiveData পর্যবেক্ষক প্যাটার্নে, পর্যবেক্ষণযোগ্য আইটেমটি কী (কী পর্যবেক্ষণ করা হয়)?

  • পর্যবেক্ষক পদ্ধতি
  • একটি LiveData অবজেক্টের ডেটা
  • UI কন্ট্রোলার
  • ViewModel অবজেক্ট

পরবর্তী পাঠ শুরু করুন: 5.3: ViewModel এবং LiveData-এর সাথে ডেটা বাইন্ডিং

এই কোর্সে অন্যান্য কোডল্যাবগুলির লিঙ্কগুলির জন্য, Android Kotlin Fundamentals codelabs ল্যান্ডিং পৃষ্ঠাটি দেখুন।