Android Kotlin Fundamentals 07.2: RecyclerView এর সাথে DiffUtil এবং ডেটা বাইন্ডিং

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

ভূমিকা

আগের কোডল্যাবে, আপনি RecyclerView এ ঘুমের গুণমান সম্পর্কে ডেটা প্রদর্শন করতে TrackMySleepQuality অ্যাপ আপডেট করেছেন। আপনি যখন আপনার প্রথম RecyclerView তৈরি করেছিলেন তখন আপনি যে কৌশলগুলি শিখেছিলেন তা বেশিরভাগ RecyclerViews জন্য যথেষ্ট যা খুব বড় নয় এমন সাধারণ তালিকাগুলি প্রদর্শন করে৷ যাইহোক, অনেকগুলি কৌশল রয়েছে যা RecyclerView বড় তালিকার জন্য আরও দক্ষ করে তোলে এবং জটিল তালিকা এবং গ্রিডগুলির জন্য আপনার কোড বজায় রাখা এবং প্রসারিত করা সহজ করে তোলে।

এই কোডল্যাবে, আপনি আগের কোডল্যাব থেকে স্লিপ-ট্র্যাকার অ্যাপ তৈরি করেন। আপনি ঘুমের ডেটার তালিকা আপডেট করার আরও কার্যকর উপায় শিখবেন এবং আপনি RecyclerView সাথে ডেটা বাইন্ডিং কীভাবে ব্যবহার করবেন তা শিখবেন। (যদি আপনার পূর্ববর্তী কোডল্যাব থেকে অ্যাপটি না থাকে তবে আপনি এই কোডল্যাবের জন্য স্টার্টার কোড ডাউনলোড করতে পারেন।)

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

  • একটি কার্যকলাপ, টুকরা, এবং দৃশ্য ব্যবহার করে একটি মৌলিক ব্যবহারকারী ইন্টারফেস তৈরি করা।
  • টুকরোগুলির মধ্যে নেভিগেট করা এবং টুকরোগুলির মধ্যে ডেটা পাস করতে safeArgs ব্যবহার করে৷
  • মডেল দেখুন, মডেল কারখানা, রূপান্তর, এবং LiveData এবং তাদের পর্যবেক্ষক দেখুন।
  • কিভাবে একটি Room ডাটাবেস তৈরি করবেন, একটি DAO তৈরি করবেন এবং সত্তাকে সংজ্ঞায়িত করবেন।
  • ডাটাবেস এবং অন্যান্য দীর্ঘ-চলমান কাজের জন্য কোরোটিনগুলি কীভাবে ব্যবহার করবেন।
  • Adapter , ViewHolder এবং আইটেম লেআউট সহ একটি মৌলিক RecyclerView কীভাবে বাস্তবায়ন করবেন।

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

  • RecyclerView দ্বারা প্রদর্শিত একটি তালিকা দক্ষতার সাথে আপডেট করতে কীভাবে DiffUtil ব্যবহার করবেন।
  • RecyclerView সাথে ডেটা বাইন্ডিং কিভাবে ব্যবহার করবেন।
  • ডেটা রূপান্তর করতে বাইন্ডিং অ্যাডাপ্টারগুলি কীভাবে ব্যবহার করবেন।

আপনি কি করবেন

  • এই সিরিজের আগের কোডল্যাব থেকে TrackMySleepQuality অ্যাপ তৈরি করুন।
  • DiffUtil ব্যবহার করে তালিকাটি দক্ষতার সাথে আপডেট করতে SleepNightAdapter আপডেট করুন।
  • ডেটা রূপান্তর করতে বাইন্ডিং অ্যাডাপ্টার ব্যবহার করে RecyclerView জন্য ডেটা বাইন্ডিং প্রয়োগ করুন।

স্লিপ-ট্র্যাকার অ্যাপটিতে দুটি স্ক্রীন রয়েছে, যা খন্ড দ্বারা উপস্থাপিত হয়, যেমনটি নীচের চিত্রে দেখানো হয়েছে।

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

এই অ্যাপটি একটি UI কন্ট্রোলার, ViewModel এবং LiveData , এবং ঘুমের ডেটা বজায় রাখার জন্য একটি Room ডেটাবেস ব্যবহার করার জন্য আর্কিটেক্ট করা হয়েছে৷

ঘুমের ডেটা একটি RecyclerView এ প্রদর্শিত হয়। এই কোডল্যাবে, আপনি RecyclerView জন্য DiffUtil এবং ডেটা-বাইন্ডিং অংশ তৈরি করেন। এই কোডল্যাবের পরে, আপনার অ্যাপটি হুবহু একই দেখাবে, তবে এটি আরও কার্যকরী এবং স্কেল এবং বজায় রাখা সহজ হবে।

আপনি আগের কোডল্যাব থেকে স্লিপট্র্যাকার অ্যাপটি ব্যবহার চালিয়ে যেতে পারেন, অথবা আপনি GitHub থেকে RecyclerViewDiffUtilDataBinding-Starter অ্যাপটি ডাউনলোড করতে পারেন।

  1. যদি প্রয়োজন হয়, GitHub থেকে RecyclerViewDiffUtilDataBinding-Starter অ্যাপটি ডাউনলোড করুন এবং Android স্টুডিওতে প্রকল্পটি খুলুন।
  2. অ্যাপটি চালান।
  3. SleepNightAdapter.kt ফাইলটি খুলুন।
  4. অ্যাপের কাঠামোর সাথে নিজেকে পরিচিত করতে কোডটি পরীক্ষা করুন। ব্যবহারকারীর কাছে ঘুমের ডেটা প্রদর্শন করতে অ্যাডাপ্টার প্যাটার্নের সাথে RecyclerView ব্যবহার করার সংক্ষিপ্ত বিবরণের জন্য নীচের চিত্রটি পড়ুন।

  • ব্যবহারকারীর ইনপুট থেকে, অ্যাপটি SleepNight অবজেক্টের একটি তালিকা তৈরি করে। প্রতিটি SleepNight অবজেক্ট একটি একক রাতের ঘুম, তার সময়কাল এবং গুণমানের প্রতিনিধিত্ব করে।
  • SleepNightAdapter SleepNight অবজেক্টের তালিকাকে এমন কিছুতে অভিযোজিত করে যা RecyclerView ব্যবহার করতে এবং প্রদর্শন করতে পারে।
  • SleepNightAdapter অ্যাডাপ্টার ViewHolders তৈরি করে যাতে ডেটা প্রদর্শনের জন্য রিসাইক্লার ভিউয়ের ভিউ, ডেটা এবং মেটা তথ্য থাকে।
  • RecyclerView SleepNightAdapter ব্যবহার করে কতগুলি আইটেম প্রদর্শন করতে হবে তা নির্ধারণ করতে ( getItemCount() )। RecyclerView ব্যবহার করে onCreateViewHolder() এবং onBindViewHolder() প্রদর্শনের জন্য ডেটার সাথে আবদ্ধ ভিউ হোল্ডার পেতে।

notifyDataSetChanged() পদ্ধতিটি অকার্যকর

RecyclerView জানাতে যে তালিকার একটি আইটেম পরিবর্তিত হয়েছে এবং আপডেট করা দরকার, বর্তমান কোডটি নিচে দেখানো হিসাবে SleepNightAdapternotifyDataSetChanged() কল করে।

var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

যাইহোক, notifyDataSetChanged() RecyclerView বলে যে পুরো তালিকাটি সম্ভাব্যভাবে অবৈধ। ফলস্বরূপ, RecyclerView স্ক্রীনে দৃশ্যমান নয় এমন আইটেমগুলি সহ তালিকার প্রতিটি আইটেমকে রিবাইন্ড করে এবং পুনরায় অঙ্কন করে। এটা অনেক অপ্রয়োজনীয় কাজ। বৃহৎ বা জটিল তালিকার জন্য, এই প্রক্রিয়াটি যথেষ্ট সময় নিতে পারে যাতে ব্যবহারকারী তালিকার মধ্য দিয়ে স্ক্রোল করার সাথে সাথে প্রদর্শনটি ফ্লিকার বা তোতলাতে থাকে।

এই সমস্যাটি সমাধান করতে, আপনি RecyclerView বলতে পারেন ঠিক কি পরিবর্তন হয়েছে৷ RecyclerView তারপর শুধুমাত্র পর্দায় পরিবর্তিত ভিউ আপডেট করতে পারে।

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

ভাগ্যক্রমে, একটি ভাল উপায় আছে.

DiffUtil দক্ষ এবং আপনার জন্য কঠোর পরিশ্রম করে

RecyclerView DiffUtil নামক একটি ক্লাস রয়েছে যা দুটি তালিকার মধ্যে পার্থক্য গণনা করার জন্য। DiffUtil একটি পুরানো তালিকা এবং একটি নতুন তালিকা নেয় এবং কী আলাদা তা বের করে। এটি যোগ করা, সরানো বা পরিবর্তিত আইটেমগুলি খুঁজে পায়। তারপরে এটি নতুন তালিকা তৈরি করতে পুরানো তালিকা থেকে ন্যূনতম সংখ্যক পরিবর্তনগুলি বের করতে ইউজিন ডব্লিউ মায়ার্সের পার্থক্য অ্যালগরিদম নামে একটি অ্যালগরিদম ব্যবহার করে।

একবার DiffUtil কি পরিবর্তিত হয়েছে তা খুঁজে বের করলে, RecyclerView সেই তথ্যটি শুধুমাত্র পরিবর্তন করা, যোগ করা, সরানো বা সরানো আইটেমগুলিকে আপডেট করতে ব্যবহার করতে পারে, যা সম্পূর্ণ তালিকা পুনরায় করার চেয়ে অনেক বেশি কার্যকর।

এই কাজটিতে, আপনি ডেটাতে পরিবর্তনের জন্য RecyclerView অপ্টিমাইজ করতে DiffUtil ব্যবহার করতে SleepNightAdapter আপগ্রেড করেন।

ধাপ 1: SleepNightDiffCallback প্রয়োগ করুন

DiffUtil ক্লাসের কার্যকারিতা ব্যবহার করার জন্য, DiffUtil.ItemCallback প্রসারিত করুন।

  1. SleepNightAdapter.kt খুলুন।
  2. SleepNightAdapter জন্য সম্পূর্ণ শ্রেণির সংজ্ঞার নীচে, SleepNightDiffCallback নামে একটি নতুন শীর্ষ-স্তরের ক্লাস তৈরি করুন যা DiffUtil.ItemCallback প্রসারিত করে। একটি জেনেরিক প্যারামিটার হিসাবে SleepNight পাস করুন।
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
  1. SleepNightDiffCallback ক্লাসের নামে কার্সার রাখুন।
  2. Alt+Enter টিপুন ( Option+Enter Mac এ) এবং সদস্যদের বাস্তবায়ন নির্বাচন করুন।
  3. যে ডায়ালগটি খোলে সেখানে, areItemsTheSame() এবং areContentsTheSame() পদ্ধতি নির্বাচন করতে শিফট-বাম-ক্লিক করুন, তারপর ওকে ক্লিক করুন।

    এটি নিচে দেখানো দুটি পদ্ধতির জন্য SleepNightDiffCallback ভিতরে স্টাব তৈরি করে। তালিকা এবং আইটেমগুলি কীভাবে পরিবর্তিত হয়েছে তা নির্ধারণ করতে DiffUtil এই দুটি পদ্ধতি ব্যবহার করে।
    override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
  1. areItemsTheSame() এর ভিতরে, TODO কোড দিয়ে প্রতিস্থাপন করুন যা পরীক্ষা করে যে দুটি পাস করা SleepNight আইটেম, oldItem এবং newItem , একই কিনা। আইটেম একই nightId থাকলে, তারা একই আইটেম, তাই true ফিরে. অন্যথায়, false ফিরে. একটি আইটেম যোগ করা, সরানো বা সরানো হয়েছে কিনা তা আবিষ্কার করতে DiffUtil এই পরীক্ষাটি ব্যবহার করে।
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem.nightId == newItem.nightId
}
  1. areContentsTheSame() এর ভিতরে, oldItem এবং newItem একই ডেটা রয়েছে কিনা তা পরীক্ষা করুন; অর্থাৎ, তারা সমান কিনা। এই সমতা পরীক্ষাটি সমস্ত ক্ষেত্র পরীক্ষা করবে, কারণ SleepNight একটি ডেটা ক্লাস। Data ক্লাস স্বয়ংক্রিয়ভাবে আপনার জন্য equals এবং কয়েকটি অন্যান্য পদ্ধতি সংজ্ঞায়িত করে। oldItem এবং newItem মধ্যে পার্থক্য থাকলে, এই কোডটি DiffUtil বলে যে আইটেমটি আপডেট করা হয়েছে।
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem == newItem
}

পরিবর্তিত একটি তালিকা প্রদর্শন করার জন্য একটি RecyclerView ব্যবহার করা একটি সাধারণ প্যাটার্ন। RecyclerView একটি অ্যাডাপ্টার ক্লাস প্রদান করে, ListAdapter , যা আপনাকে একটি RecyclerView অ্যাডাপ্টার তৈরি করতে সাহায্য করে যা একটি তালিকা দ্বারা সমর্থিত।

ListAdapter আপনার জন্য তালিকার ট্র্যাক রাখে এবং তালিকা আপডেট করা হলে অ্যাডাপ্টারকে অবহিত করে।

ধাপ 1: ListAdapter প্রসারিত করতে আপনার অ্যাডাপ্টার পরিবর্তন করুন

  1. SleepNightAdapter.kt ফাইলে, ListAdapter প্রসারিত করতে SleepNightAdapter এর ক্লাস স্বাক্ষর পরিবর্তন করুন।
  2. অনুরোধ করা হলে, androidx.recyclerview.widget.ListAdapter আমদানি করুন।
  3. SleepNightAdapter.ViewHolder এর আগে ListAdapter এ প্রথম আর্গুমেন্ট হিসেবে SleepNight যোগ করুন।
  4. SleepNightDiffCallback() কনস্ট্রাক্টরের একটি প্যারামিটার হিসাবে যোগ করুন। তালিকায় কী পরিবর্তন হয়েছে তা বের করতে ListAdapter এটি ব্যবহার করবে। আপনার সমাপ্ত SleepNightAdapter ক্লাসের স্বাক্ষর নীচে দেখানো উচিত।
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. SleepNightAdapter ক্লাসের ভিতরে, সেটার সহ data ক্ষেত্র মুছুন। আপনার আর এটির প্রয়োজন নেই, কারণ ListAdapter আপনার জন্য তালিকার ট্র্যাক রাখে।
  2. getItemCount() এর ওভাররাইড মুছুন, কারণ ListAdapter আপনার জন্য এই পদ্ধতিটি প্রয়োগ করে।
  3. onBindViewHolder() এর ত্রুটি থেকে পরিত্রাণ পেতে, item ভেরিয়েবল পরিবর্তন করুন। একটি item পেতে data ব্যবহার করার পরিবর্তে, ListAdapter প্রদান করে getItem(position) পদ্ধতিতে কল করুন।
val item = getItem(position)

ধাপ 2: তালিকা আপডেট রাখতে SubmitList() ব্যবহার করুন

একটি পরিবর্তিত তালিকা উপলব্ধ হলে আপনার কোড ListAdapter কে বলতে হবে। ListAdapter submitList() নামে একটি পদ্ধতি সরবরাহ করে যাতে ListAdapter বলা হয় যে তালিকার একটি নতুন সংস্করণ উপলব্ধ। যখন এই পদ্ধতিটি কল করা হয়, ListAdapter পুরানোটির সাথে নতুন তালিকার পার্থক্য করে এবং যোগ করা, সরানো, সরানো বা পরিবর্তিত আইটেমগুলি সনাক্ত করে। তারপর ListAdapter RecyclerView দ্বারা দেখানো আইটেম আপডেট করে।

  1. SleepTrackerFragment.kt খুলুন।
  2. onCreateView() -এ, sleepTrackerViewModel এর পর্যবেক্ষক-এ, আপনার মুছে ফেলা data ভেরিয়েবলটি রেফারেন্স করা হয়েছে এমন ত্রুটি খুঁজুন।
  3. adapter.data = it adapter.submitList(it) এ কল দিয়ে প্রতিস্থাপন করুন। আপডেট করা কোড নিচে দেখানো হয়েছে।

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.submitList(it)
   }
})
  1. আপনার অ্যাপ চালান। এটি দ্রুত সঞ্চালিত হয়, সম্ভবত আপনার তালিকা ছোট হলে লক্ষণীয় নয়।

এই টাস্কে, আপনি ডেটা বাইন্ডিং সেট আপ করতে পূর্ববর্তী কোডল্যাবগুলির মতো একই কৌশল ব্যবহার করেন এবং আপনি findViewById() এর জন্য কলগুলি বাদ দেন।

ধাপ 1: লেআউট ফাইলে ডেটা বাইন্ডিং যোগ করুন

  1. টেক্সট ট্যাবে list_item_sleep_night.xml লেআউট ফাইলটি খুলুন।
  2. ConstraintLayout ট্যাগে কার্সার রাখুন এবং Alt+Enter চাপুন ( Option+Enter একটি ম্যাকে)। উদ্দেশ্য মেনু ("দ্রুত সমাধান" মেনু) খোলে।
  3. কনভার্ট টু ডাটা বাইন্ডিং লেআউট নির্বাচন করুন। এটি লেআউটটিকে <layout> এ মোড়ক করে এবং ভিতরে একটি <data> ট্যাগ যোগ করে।
  4. উপরের দিকে স্ক্রোল করুন, যদি প্রয়োজন হয়, এবং <data> ট্যাগের ভিতরে, sleep নামে একটি পরিবর্তনশীল ঘোষণা করুন।
  5. এর type SleepNight এর সম্পূর্ণ যোগ্য নাম করুন, com.example.android.trackmysleepquality.database.SleepNight । আপনার সমাপ্ত <data> ট্যাগ নিচের মত দেখা উচিত।
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Binding অবজেক্ট তৈরি করতে বাধ্য করতে, Build > Clean Project নির্বাচন করুন, তারপর Build > Rebuild Project নির্বাচন করুন। (যদি আপনার এখনও সমস্যা হয়, ফাইল > ক্যাশে বাতিল করুন / পুনঃসূচনা করুন নির্বাচন করুন।) ListItemSleepNightBinding বাইন্ডিং অবজেক্ট, সম্পর্কিত কোড সহ, প্রকল্পের তৈরি করা ফাইলগুলিতে যোগ করা হয়।

ধাপ 2: ডেটা বাইন্ডিং ব্যবহার করে আইটেম লেআউটটি স্ফীত করুন

  1. SleepNightAdapter.kt খুলুন।
  2. ViewHolder ক্লাসে, from() পদ্ধতিটি সন্ধান করুন।
  3. view ভেরিয়েবলের ঘোষণা মুছুন।

মুছে ফেলার কোড:

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. যেখানে view ভেরিয়েবলটি ছিল, সেখানে binding নামে একটি নতুন ভেরিয়েবল সংজ্ঞায়িত করুন যা ListItemSleepNightBinding বাইন্ডিং অবজেক্টকে স্ফীত করে, যেমনটি নীচে দেখানো হয়েছে। বাইন্ডিং অবজেক্টের প্রয়োজনীয় আমদানি করুন।
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. ফাংশন শেষে view রিটার্ন না করে রিটার্ন binding
return ViewHolder(binding)
  1. ত্রুটি থেকে পরিত্রাণ পেতে, আপনার কার্সারটি binding শব্দে রাখুন। অভিপ্রায় মেনু খুলতে Alt+Enter ( একটি Mac-এ Option+Enter ) টিপুন।
  1. 'ListItemSleepNightBinding'-এ 'ভিউহোল্ডার' ক্লাসের প্রাথমিক কনস্ট্রাক্টরের 'itemView' ধরনের প্যারামিটার পরিবর্তন করুন। এটি ViewHolder ক্লাসের প্যারামিটার প্রকার আপডেট করে।

  1. স্বাক্ষরের পরিবর্তন দেখতে ViewHolder শ্রেণি সংজ্ঞা পর্যন্ত স্ক্রোল করুন। আপনি itemView এর জন্য একটি ত্রুটি দেখতে পাচ্ছেন, কারণ আপনি from() পদ্ধতিতে bindingitemView পরিবর্তন করেছেন।

    ViewHolder ক্লাসের সংজ্ঞায়, itemView এর সংঘটনগুলির একটিতে ডান-ক্লিক করুন এবং রিফ্যাক্টর > পুনঃনামকরণ নির্বাচন করুন। binding নাম পরিবর্তন করুন.
  2. কনস্ট্রাক্টর প্যারামিটারটিকে val এর সাথে binding উপসর্গ করুন যাতে এটি একটি বৈশিষ্ট্য হয়।
  3. অভিভাবক শ্রেণীর কলে, RecyclerView.ViewHolder , binding থেকে binding.root এ প্যারামিটার পরিবর্তন করুন। আপনাকে একটি View পাস করতে হবে এবং binding.root হল আপনার আইটেম লেআউটের রুট ConstraintLayout
  4. আপনার সমাপ্ত ক্লাস ঘোষণা নীচের কোড মত দেখতে হবে.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

এছাড়াও আপনি findViewById() কল করার জন্য একটি ত্রুটি দেখতে পাচ্ছেন এবং আপনি পরবর্তীতে এটি ঠিক করবেন।

ধাপ 3: findViewById() প্রতিস্থাপন করুন

আপনি এখন findViewById() এর পরিবর্তে binding অবজেক্ট ব্যবহার করতে sleepLength , quality এবং qualityImage বৈশিষ্ট্য আপডেট করতে পারেন।

  1. নিচে দেখানো হিসাবে binding অবজেক্টের ভিউ ব্যবহার করতে sleepLength , qualityString , এবং qualityImage এর প্রারম্ভিকতা পরিবর্তন করুন। এর পরে, আপনার কোড আর কোনো ত্রুটি দেখাবে না।
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

বাইন্ডিং অবজেক্টের জায়গায়, আপনাকে আর sleepLength , quality এবং qualityImage বৈশিষ্ট্যগুলিকে সংজ্ঞায়িত করতে হবে না। DataBinding লুকআপগুলিকে ক্যাশে করবে, তাই এই বৈশিষ্ট্যগুলি ঘোষণা করার দরকার নেই।

  1. sleepLength , quality , এবং qualityImage ইমেজ প্রোপার্টি নামের উপর রাইট-ক্লিক করুন। রিফ্যাক্টর > ইনলাইন নির্বাচন করুন বা Control+Command+N টিপুন (একটি Mac-এ Option+Command+N )।
  2. আপনার অ্যাপ চালান। (আপনার প্রকল্পে ত্রুটি থাকলে আপনাকে পরিষ্কার এবং পুনর্নির্মাণ করতে হতে পারে।)

এই টাস্কে, আপনি আপনার ভিউয়ে ডেটা সেট করতে বাইন্ডিং অ্যাডাপ্টারের সাথে ডেটা বাইন্ডিং ব্যবহার করতে আপনার অ্যাপ আপগ্রেড করেন।

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

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

ধাপ 1: বাইন্ডিং অ্যাডাপ্টার তৈরি করুন

মনে রাখবেন যে ধাপে আপনাকে বেশ কয়েকটি ক্লাস আমদানি করতে হবে এবং এটি পৃথকভাবে বলা হবে না।

  1. SleepNightAdapater.kt খুলুন।
  2. ViewHolder ক্লাসের ভিতরে, bind() পদ্ধতিটি খুঁজুন এবং এই পদ্ধতিটি কী করে তা নিজেকে মনে করিয়ে দিন। আপনি কোডটি নেবেন যা binding.sleepLength , binding.quality এবং binding.qualityImage এর মান গণনা করে এবং পরিবর্তে অ্যাডাপ্টারের ভিতরে এটি ব্যবহার করুন। (আপাতত, কোডটি যেমন আছে তেমনি রেখে দিন; আপনি এটিকে পরবর্তী ধাপে সরান।)
  3. sleeptracker প্যাকেজে, BindingUtils.kt নামে একটি ফাইল তৈরি করুন এবং খুলুন।
  4. TextView একটি এক্সটেনশন ফাংশন ঘোষণা করুন, setSleepDurationFormatted নামে পরিচিত, এবং একটি SleepNight পাস করুন। এই ফাংশনটি ঘুমের সময়কাল গণনা এবং ফর্ম্যাট করার জন্য আপনার অ্যাডাপ্টার হবে।
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
  1. setSleepDurationFormatted এর বডিতে, ViewHolder.bind() এর মত করে ভিউতে ডেটা আবদ্ধ করুন। convertDurationToFormatted() কে কল করুন এবং তারপরে TextView এর text বিন্যাসিত পাঠ্যে সেট করুন। (কারণ এটি TextView এ একটি এক্সটেনশন ফাংশন, আপনি সরাসরি text সম্পত্তি অ্যাক্সেস করতে পারেন।)
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
  1. এই বাইন্ডিং অ্যাডাপ্টার সম্পর্কে ডেটা বাইন্ডিং বলতে, @BindingAdapter দিয়ে ফাংশনটি টীকা করুন।
  2. এই ফাংশনটি sleepDurationFormatted অ্যাট্রিবিউটের অ্যাডাপ্টার, তাই @BindingAdapter এ একটি যুক্তি হিসাবে sleepDurationFormatted পাস করুন।
@BindingAdapter("sleepDurationFormatted")
  1. দ্বিতীয় অ্যাডাপ্টার একটি SleepNight অবজেক্টের মানের উপর ভিত্তি করে ঘুমের গুণমান সেট করে। TextView setSleepQualityString() নামে একটি এক্সটেনশন ফাংশন তৈরি করুন এবং একটি SleepNight পাস করুন।
  2. বডিতে, আপনি ViewHolder.bind() এ যেমনটি করেছিলেন ভিউতে ডেটা আবদ্ধ করুন। convertNumericQualityToString কল করুন এবং text সেট করুন।
  3. @BindingAdapter("sleepQualityString") দিয়ে ফাংশনটি টীকা করুন।
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
   text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
  1. তৃতীয় বাইন্ডিং অ্যাডাপ্টার একটি ইমেজ ভিউতে ইমেজ সেট করে। ImageView এ এক্সটেনশন ফাংশন তৈরি করুন, setSleepImage কল করুন এবং ViewHolder.bind() থেকে কোডটি ব্যবহার করুন, যেমনটি নীচে দেখানো হয়েছে।
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
   setImageResource(when (item.sleepQuality) {
       0 -> R.drawable.ic_sleep_0
       1 -> R.drawable.ic_sleep_1
       2 -> R.drawable.ic_sleep_2
       3 -> R.drawable.ic_sleep_3
       4 -> R.drawable.ic_sleep_4
       5 -> R.drawable.ic_sleep_5
       else -> R.drawable.ic_sleep_active
   })
}

ধাপ 2: SleepNightAdapter আপডেট করুন

  1. SleepNightAdapter.kt খুলুন।
  2. bind() পদ্ধতিতে সবকিছু মুছুন, কারণ আপনি এখন আপনার জন্য এই কাজটি করতে ডেটা বাইন্ডিং এবং আপনার নতুন অ্যাডাপ্টার ব্যবহার করতে পারেন।
fun bind(item: SleepNight) {
}
  1. bind() ভিতরে, item ঘুম বরাদ্দ করুন, কারণ আপনাকে আপনার নতুন SleepNight সম্পর্কে বাইন্ডিং অবজেক্টকে বলতে হবে।
binding.sleep = item
  1. সেই লাইনের নীচে, binding.executePendingBindings() যোগ করুন। এই কলটি হল একটি অপ্টিমাইজেশান যা ডাটা বাইন্ডিংকে অবিলম্বে যেকোনো মুলতুবি বাইন্ডিং কার্যকর করতে বলে। আপনি যখন একটি RecyclerView এ বাইন্ডিং অ্যাডাপ্টার ব্যবহার করেন তখন executePendingBindings() কল করা সর্বদা একটি ভাল ধারণা, কারণ এটি দৃশ্যের আকারকে কিছুটা গতি দিতে পারে।
 binding.executePendingBindings()

ধাপ 3: XML লেআউটে বাইন্ডিং যোগ করুন

  1. list_item_sleep_night.xml খুলুন।
  2. ImageView তে, বাইন্ডিং অ্যাডাপ্টারের মতো একই নামের একটি app প্রপার্টি যোগ করুন যা ইমেজ সেট করে। নিচে দেখানো হিসাবে, sleep পরিবর্তনশীল পাস.

    এই বৈশিষ্ট্যটি অ্যাডাপ্টারের মাধ্যমে ভিউ এবং বাইন্ডিং অবজেক্টের মধ্যে সংযোগ তৈরি করে। যখনই sleepImage রেফারেন্স করা হয়, অ্যাডাপ্টারটি SleepNight থেকে ডেটা মানিয়ে নেবে।
app:sleepImage="@{sleep}"
  1. sleep_length এবং quality_string টেক্সট ভিউ এর জন্য একই কাজ করুন। যখনই sleepDurationFormatted বা sleepQualityString উল্লেখ করা হয়, তখন অ্যাডাপ্টারগুলি SleepNight থেকে ডেটা গ্রহণ করবে।
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
  1. আপনার অ্যাপ চালান। এটা ঠিক আগের মতই কাজ করে। বাইন্ডিং অ্যাডাপ্টারগুলি ডেটা পরিবর্তনের সাথে সাথে ভিউগুলি ফর্ম্যাটিং এবং আপডেট করার সমস্ত কাজের যত্ন নেয়, ViewHolder সরল করে এবং কোডটিকে আগের তুলনায় অনেক ভাল কাঠামো দেয়৷

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

অভিনন্দন! এই মুহুর্তে আপনি অ্যান্ড্রয়েডে RecyclerView আয়ত্ত করার পথে ভাল আছেন।

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

DiffUtil :

  • RecyclerView DiffUtil নামক একটি ক্লাস রয়েছে যা দুটি তালিকার মধ্যে পার্থক্য গণনা করার জন্য।
  • DiffUtil ItemCallBack নামে একটি ক্লাস রয়েছে যা আপনি দুটি তালিকার মধ্যে পার্থক্য বের করার জন্য প্রসারিত করেন।
  • ItemCallback ক্লাসে, আপনাকে অবশ্যই areItemsTheSame() এবং areContentsTheSame() পদ্ধতিগুলিকে ওভাররাইড করতে হবে।

ListAdapter :

  • বিনামূল্যে কিছু তালিকা ব্যবস্থাপনা পেতে, আপনি RecyclerView.Adapter এর পরিবর্তে ListAdapter ক্লাস ব্যবহার করতে পারেন। যাইহোক, আপনি যদি ListAdapter ব্যবহার করেন তবে আপনাকে অন্যান্য লেআউটের জন্য আপনার নিজের অ্যাডাপ্টার লিখতে হবে, এই কারণেই এই কোডল্যাবটি আপনাকে দেখায় কিভাবে এটি করতে হয়।
  • অ্যান্ড্রয়েড স্টুডিওতে উদ্দেশ্য মেনু খুলতে, কোডের যেকোনো আইটেমে কার্সার রাখুন এবং Alt+Enter ( Mac-এ Option+Enter ) টিপুন। এই মেনুটি কোড রিফ্যাক্টরিং এবং পদ্ধতি বাস্তবায়নের জন্য স্টাব তৈরির জন্য বিশেষভাবে সহায়ক। মেনুটি প্রসঙ্গ-সংবেদনশীল, তাই সঠিক মেনু পেতে আপনাকে কার্সার ঠিক রাখতে হবে।

ডেটা বাঁধাই:

  • দৃশ্যের সাথে ডেটা আবদ্ধ করতে আইটেম লেআউটে ডেটা বাইন্ডিং ব্যবহার করুন।

বাঁধাই অ্যাডাপ্টার:

  • আপনি পূর্বে ডেটা থেকে স্ট্রিং তৈরি করতে Transformations ব্যবহার করেছিলেন। আপনি যদি বিভিন্ন বা জটিল ধরণের ডেটা আবদ্ধ করতে চান তবে ডেটা বাইন্ডিং ব্যবহার করতে সহায়তা করার জন্য বাইন্ডিং অ্যাডাপ্টার সরবরাহ করুন।
  • একটি বাইন্ডিং অ্যাডাপ্টার ঘোষণা করতে, একটি আইটেম এবং একটি দৃশ্য গ্রহণ করে এমন একটি পদ্ধতি নির্ধারণ করুন এবং @BindingAdapter সাথে পদ্ধতিটি টীকা করুন। কোটলিনে, আপনি View এ এক্সটেনশন ফাংশন হিসাবে বাইন্ডিং অ্যাডাপ্টার লিখতে পারেন। অ্যাডাপ্টার অ্যাডাপ্ট করে এমন সম্পত্তির নামে পাস করুন। যেমন:
@BindingAdapter("sleepDurationFormatted")
  • XML লেআউটে, বাইন্ডিং অ্যাডাপ্টারের মতো একই নামের একটি app সম্পত্তি সেট করুন। ডেটা সহ একটি ভেরিয়েবল পাস করুন। যেমন:
.app:sleepDurationFormatted="@{sleep}"

Udacity কোর্স:

অ্যান্ড্রয়েড বিকাশকারী ডকুমেন্টেশন:

অন্যান্য সম্পদ:

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

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

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

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

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

প্রশ্ন 1

নিচের কোনটি DiffUtil ব্যবহার করতে হবে? প্রযোজ্য সব নির্বাচন করুন.

ItemCallBack ক্লাস প্রসারিত করুন।

▢ ওভাররাইড areItemsTheSame()

▢ ওভাররাইড areContentsTheSame()

▢ আইটেমের মধ্যে পার্থক্য ট্র্যাক করতে ডেটা বাইন্ডিং ব্যবহার করুন।

প্রশ্ন 2

বাইন্ডিং অ্যাডাপ্টার সম্পর্কে নিচের কোনটি সত্য?

▢ একটি বাইন্ডিং অ্যাডাপ্টার হল একটি ফাংশন যা @BindingAdapter দিয়ে টীকা করা হয়েছে।

▢ একটি বাইন্ডিং অ্যাডাপ্টার ব্যবহার করে আপনি ভিউ হোল্ডার থেকে ডেটা ফরম্যাটিং আলাদা করতে পারবেন।

▢ আপনি যদি বাইন্ডিং অ্যাডাপ্টার ব্যবহার করতে চান তাহলে আপনাকে অবশ্যই একটি RecyclerViewAdapter ব্যবহার করতে হবে।

▢ বাইন্ডিং অ্যাডাপ্টারগুলি একটি ভাল সমাধান যখন আপনাকে জটিল ডেটা রূপান্তর করতে হবে৷

প্রশ্ন 3

আপনার কখন বাইন্ডিং অ্যাডাপ্টারের পরিবর্তে Transformations ব্যবহার করার কথা বিবেচনা করা উচিত? প্রযোজ্য সব নির্বাচন করুন.

▢ আপনার ডেটা সহজ।

▢ আপনি একটি স্ট্রিং ফর্ম্যাট করছেন।

▢ আপনার তালিকা অনেক লম্বা।

▢ আপনার ViewHolder শুধুমাত্র একটি ভিউ রয়েছে।

পরবর্তী পাঠ শুরু করুন: 7.3: রিসাইক্লারভিউ সহ গ্রিডলেআউট