অ্যান্ড্রয়েড কোটলিন ফান্ডামেন্টালস 09.2: ওয়ার্ক ম্যানেজার

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

ভূমিকা

বেশিরভাগ বাস্তব-বিশ্বের অ্যাপ্লিকেশনগুলির দীর্ঘ-চলমান ব্যাকগ্রাউন্ড কাজগুলি সম্পাদন করতে হবে। উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন একটি সার্ভারে ফাইল আপলোড করতে পারে, একটি সার্ভার থেকে ডেটা সিঙ্ক করতে পারে এবং এটি একটি Room ডাটাবেসে সংরক্ষণ করতে পারে, একটি সার্ভারে লগ পাঠাতে পারে, বা ডেটাতে ব্যয়বহুল ক্রিয়াকলাপ চালাতে পারে। এই ধরনের ক্রিয়াকলাপগুলি ব্যাকগ্রাউন্ডে, UI থ্রেডের বাইরে (প্রধান থ্রেড) করা উচিত। ব্যাকগ্রাউন্ড কাজগুলি ডিভাইসের সীমিত সংস্থানগুলি ব্যবহার করে, যেমন RAM এবং ব্যাটারি। সঠিকভাবে পরিচালনা না করা হলে এটি ব্যবহারকারীর জন্য একটি খারাপ অভিজ্ঞতা হতে পারে।

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

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

  • ViewModel , LiveData এবং Room অ্যান্ড্রয়েড আর্কিটেকচার উপাদানগুলি কীভাবে ব্যবহার করবেন।
  • কিভাবে একটি LiveData ক্লাসে রূপান্তর করতে হয়।
  • কিভাবে একটি করোটিন তৈরি এবং চালু করবেন।
  • ডাটা বাইন্ডিং এ বাইন্ডিং অ্যাডাপ্টার কিভাবে ব্যবহার করবেন।
  • একটি সংগ্রহস্থল প্যাটার্ন ব্যবহার করে ক্যাশে ডেটা কীভাবে লোড করবেন।

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

  • কীভাবে একজন Worker তৈরি করবেন, যা কাজের একটি ইউনিটকে প্রতিনিধিত্ব করে।
  • কাজ সম্পাদন করার অনুরোধ করার জন্য কিভাবে একটি WorkRequest তৈরি করবেন।
  • কিভাবে এবং কখন একজন কর্মী চালানো উচিত তা নির্ধারণ করতে WorkRequest এ কীভাবে সীমাবদ্ধতা যুক্ত করবেন।
  • ব্যাকগ্রাউন্ড টাস্ক শিডিউল করতে WorkManager কিভাবে ব্যবহার করবেন।

আপনি কি করবেন

  • নেটওয়ার্ক থেকে DevBytes ভিডিও প্লেলিস্ট প্রাক-আনয়নের জন্য একটি ব্যাকগ্রাউন্ড টাস্ক চালানোর জন্য একজন কর্মী তৈরি করুন।
  • পর্যায়ক্রমে চালানোর জন্য কর্মী নির্ধারণ করুন।
  • WorkRequest এ সীমাবদ্ধতা যোগ করুন।
  • একটি পর্যায়ক্রমিক WorkRequest সময়সূচী করুন যা দিনে একবার কার্যকর করা হয়।

এই কোডল্যাবে, আপনি DevBytes অ্যাপে কাজ করেন যা আপনি আগের কোডল্যাবে তৈরি করেছেন। (যদি আপনার কাছে এই অ্যাপটি না থাকে, আপনি এই পাঠের জন্য স্টার্টার কোড ডাউনলোড করতে পারেন।)

DevBytes অ্যাপটি DevByte ভিডিওগুলির একটি তালিকা প্রদর্শন করে, যা Google Android ডেভেলপার রিলেশনস টিমের তৈরি ছোট টিউটোরিয়াল। ভিডিওগুলি Android বিকাশের জন্য বিকাশকারী বৈশিষ্ট্য এবং সর্বোত্তম অনুশীলনগুলি উপস্থাপন করে৷

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

এই টাস্কে, আপনি স্টার্টার কোড ডাউনলোড এবং পরিদর্শন করুন।

ধাপ 1: স্টার্টার অ্যাপটি ডাউনলোড করুন এবং চালান

আপনি আগের কোডল্যাবে তৈরি করা DevBytes অ্যাপের মাধ্যমে কাজ চালিয়ে যেতে পারেন (যদি আপনার কাছে থাকে)। বিকল্পভাবে আপনি স্টার্টার অ্যাপটি ডাউনলোড করতে পারেন।

এই টাস্কে, আপনি স্টার্টার অ্যাপ ডাউনলোড করে রান করুন এবং স্টার্টার কোড পরীক্ষা করুন।

  1. আপনার যদি ইতিমধ্যেই DevBytes অ্যাপ না থাকে, তাহলে GitHub থেকে DevBytesRepository প্রকল্প থেকে এই কোডল্যাবের জন্য DevBytes স্টার্টার কোডটি ডাউনলোড করুন।
  2. কোডটি আনজিপ করুন এবং অ্যান্ড্রয়েড স্টুডিওতে প্রকল্পটি খুলুন।
  3. আপনার পরীক্ষা ডিভাইস বা এমুলেটরকে ইন্টারনেটের সাথে সংযুক্ত করুন, যদি এটি ইতিমধ্যে সংযুক্ত না থাকে। অ্যাপটি তৈরি করুন এবং চালান। অ্যাপটি নেটওয়ার্ক থেকে DevByte ভিডিওগুলির তালিকা নিয়ে আসে এবং সেগুলি প্রদর্শন করে।
  4. অ্যাপে, YouTube অ্যাপে খুলতে যেকোনো ভিডিওতে ট্যাপ করুন।

ধাপ 2: কোডটি অন্বেষণ করুন

স্টার্টার অ্যাপটি অনেক কোড নিয়ে আসে যা আগের কোডল্যাবে চালু করা হয়েছিল। এই কোডল্যাবের স্টার্টার কোডে নেটওয়ার্কিং, ইউজার ইন্টারফেস, অফলাইন ক্যাশে এবং রিপোজিটরি মডিউল রয়েছে। আপনি WorkManager ব্যবহার করে ব্যাকগ্রাউন্ড টাস্ক শিডিউল করার উপর ফোকাস করতে পারেন।

  1. অ্যান্ড্রয়েড স্টুডিওতে, সমস্ত প্যাকেজ প্রসারিত করুন।
  2. database প্যাকেজ অন্বেষণ. প্যাকেজটিতে ডাটাবেস সত্তা এবং স্থানীয় ডাটাবেস রয়েছে, যা Room ব্যবহার করে বাস্তবায়িত হয়।
  3. repository প্যাকেজ অন্বেষণ. প্যাকেজটিতে VideosRepository ক্লাস রয়েছে যা অ্যাপের বাকি অংশ থেকে ডেটা স্তরকে বিমূর্ত করে।
  4. আপনার নিজের থেকে বাকি স্টার্টার কোড অন্বেষণ করুন, এবং পূর্ববর্তী কোডল্যাবের সাহায্যে।

WorkManager হল Android আর্কিটেকচার উপাদানগুলির মধ্যে একটি এবং Android Jetpack এর অংশ৷ WorkManager হল ব্যাকগ্রাউন্ডের কাজের জন্য যা স্থগিত করা যায় এবং নিশ্চিতভাবে কার্যকর করার প্রয়োজন হয়:

  • Deferrable মানে কাজটি অবিলম্বে চালানোর প্রয়োজন নেই। উদাহরণস্বরূপ, সার্ভারে বিশ্লেষণাত্মক ডেটা পাঠানো বা পটভূমিতে ডেটাবেস সিঙ্ক করা এমন কাজ যা পিছিয়ে দেওয়া যেতে পারে।
  • গ্যারান্টিড এক্সিকিউশন মানে অ্যাপটি প্রস্থান করলে বা ডিভাইস রিস্টার্ট করলেও টাস্কটি চলবে।

যখন WorkManager ব্যাকগ্রাউন্ডের কাজ চালায়, এটি সামঞ্জস্যের সমস্যা এবং ব্যাটারি এবং সিস্টেমের স্বাস্থ্যের জন্য সর্বোত্তম অনুশীলনের যত্ন নেয়। WorkManager API স্তর 14-এ ফিরে সামঞ্জস্যের প্রস্তাব দেয়৷ WorkManager একটি ব্যাকগ্রাউন্ড টাস্ক শিডিউল করার জন্য একটি উপযুক্ত উপায় বেছে নেয়, ডিভাইস API স্তরের উপর নির্ভর করে৷ এটি JobScheduler ব্যবহার করতে পারে (API 23 এবং উচ্চতর) অথবা AlarmManager এবং BroadcastReceiver এর সংমিশ্রণ।

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

এই কোডল্যাবে, আপনি দিনে একবার নেটওয়ার্ক থেকে DevBytes ভিডিও প্লেলিস্ট প্রাক-আনয়নের জন্য একটি টাস্ক নির্ধারণ করেন। এই টাস্ক শিডিউল করতে, আপনি WorkManager লাইব্রেরি ব্যবহার করুন।

  1. build.gradle (Module:app) ফাইলটি খুলুন এবং প্রকল্পে WorkManager নির্ভরতা যোগ করুন।

    আপনি যদি লাইব্রেরির সর্বশেষ সংস্করণ ব্যবহার করেন, তাহলে সমাধান অ্যাপটি প্রত্যাশা অনুযায়ী কম্পাইল করা উচিত। যদি এটি না হয়, সমস্যাটি সমাধান করার চেষ্টা করুন, অথবা নীচে দেখানো লাইব্রেরি সংস্করণে ফিরে যান৷
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
  1. আপনার প্রকল্প সিঙ্ক করুন এবং নিশ্চিত করুন যে কোন সংকলন ত্রুটি নেই।

আপনি প্রকল্পে কোড যোগ করার আগে, WorkManager লাইব্রেরিতে নিম্নলিখিত ক্লাসগুলির সাথে নিজেকে পরিচিত করুন:

  • Worker
    এই ক্লাসটি যেখানে আপনি পটভূমিতে চালানোর জন্য প্রকৃত কাজ (টাস্ক) সংজ্ঞায়িত করেন। আপনি এই ক্লাসটি প্রসারিত করুন এবং doWork() পদ্ধতিটি ওভাররাইড করুন। doWork() পদ্ধতি হল যেখানে আপনি পটভূমিতে সঞ্চালনের জন্য কোড রাখেন, যেমন সার্ভারের সাথে ডেটা সিঙ্ক করা বা ছবি প্রসেস করা। আপনি এই কাজে Worker বাস্তবায়ন করুন।
  • WorkRequest
    এই শ্রেণীটি কর্মীকে ব্যাকগ্রাউন্ডে চালানোর জন্য একটি অনুরোধ উপস্থাপন করে। কিভাবে এবং কখন কর্মী টাস্ক চালাতে হবে তা কনফিগার করতে WorkRequest ব্যবহার করুন, যেমন ডিভাইস প্লাগ ইন করা বা Wi-Fi কানেক্ট করা Constraints সাহায্যে। আপনি পরবর্তী টাস্কে WorkRequest বাস্তবায়ন করুন।
  • WorkManager
    এই ক্লাস সময়সূচী এবং আপনার WorkRequest . WorkManager কাজের অনুরোধের সময়সূচী করে যা আপনার নির্দিষ্ট করা সীমাবদ্ধতাগুলিকে সম্মান করার সময় সিস্টেম সংস্থানগুলির উপর লোড ছড়িয়ে দেয়। আপনি পরবর্তী টাস্কে WorkManager প্রয়োগ করুন।

ধাপ 1: একজন কর্মী তৈরি করুন

এই টাস্কে, আপনি পটভূমিতে DevBytes ভিডিও প্লেলিস্ট প্রাক-আনয়নের জন্য একজন Worker যোগ করুন।

  1. devbyteviewer প্যাকেজের ভিতরে, work নামে একটি নতুন প্যাকেজ তৈরি করুন।
  2. work প্যাকেজের ভিতরে, RefreshDataWorker নামে একটি নতুন কোটলিন ক্লাস তৈরি করুন।
  3. RefreshDataWorker ক্লাস থেকে CoroutineWorker ক্লাস প্রসারিত করুন। কনস্ট্রাক্টর প্যারামিটার হিসাবে context এবং WorkerParameters পাস করুন।
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
       CoroutineWorker(appContext, params) {
}
  1. বিমূর্ত শ্রেণীর ত্রুটি সমাধান করতে, RefreshDataWorker ক্লাসের মধ্যে doWork() পদ্ধতিটি ওভাররাইড করুন।
override suspend fun doWork(): Result {
  return Result.success()
}

একটি সাসপেন্ডিং ফাংশন এমন একটি ফাংশন যা পরে বিরতি এবং পুনরায় শুরু করা যেতে পারে। একটি সাসপেন্ডিং ফাংশন একটি দীর্ঘ চলমান অপারেশন চালাতে পারে এবং মূল থ্রেড ব্লক না করে এটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে পারে।

ধাপ 2: doWork () বাস্তবায়ন করুন

Worker ক্লাসের ভিতরে doWork() পদ্ধতিটিকে একটি ব্যাকগ্রাউন্ড থ্রেডে ডাকা হয়। পদ্ধতিটি সিঙ্ক্রোনাসভাবে কাজ করে, এবং একটি ListenableWorker.Result অবজেক্ট ফিরিয়ে দিতে হবে। অ্যান্ড্রয়েড সিস্টেম একজন Worker তার কার্য সম্পাদন শেষ করতে এবং একটি ListenableWorker.Result বস্তু ফেরত দিতে সর্বোচ্চ 10 মিনিট সময় দেয়। এই সময়ের মেয়াদ শেষ হওয়ার পরে, সিস্টেমটি জোর করে Worker বন্ধ করে দেয়।

একটি ListenableWorker.Result অবজেক্ট তৈরি করতে, পটভূমি কাজের সমাপ্তির স্থিতি নির্দেশ করতে নিম্নলিখিত স্ট্যাটিক পদ্ধতিগুলির মধ্যে একটিতে কল করুন:

  • Result.success() —কাজ সফলভাবে সম্পন্ন হয়েছে।
  • Result.failure() — একটি স্থায়ী ব্যর্থতার সাথে কাজ সম্পন্ন হয়েছে।
  • Result.retry() —কাজ একটি ক্ষণস্থায়ী ব্যর্থতার সম্মুখীন হয়েছে এবং পুনরায় চেষ্টা করা উচিত।

এই টাস্কে, আপনি নেটওয়ার্ক থেকে DevBytes ভিডিও প্লেলিস্ট আনতে doWork() পদ্ধতি প্রয়োগ করেন। আপনি নেটওয়ার্ক থেকে ডেটা পুনরুদ্ধার করতে VideosRepository ক্লাসে বিদ্যমান পদ্ধতিগুলি পুনরায় ব্যবহার করতে পারেন।

  1. RefreshDataWorker ক্লাসে, doWork() এর ভিতরে, একটি VideosDatabase অবজেক্ট এবং একটি VideosRepository অবজেক্ট তৈরি এবং ইনস্ট্যান্টিয়েট করুন।
override suspend fun doWork(): Result {
   val database = getDatabase(applicationContext)
   val repository = VideosRepository(database)

   return Result.success()
}
  1. RefreshDataWorker ক্লাসে, doWork() এর ভিতরে, return স্টেটমেন্টের উপরে, try ব্লকের ভিতরে refreshVideos() পদ্ধতিতে কল করুন। কর্মী চালানো হলে ট্র্যাক করতে একটি লগ যোগ করুন।
try {
   repository.refreshVideos( )
   Timber.d("Work request for sync is run")
   } catch (e: HttpException) {
   return Result.retry()
}

"অমীমাংসিত রেফারেন্স" ত্রুটি সমাধান করতে, retrofit2.HttpException আমদানি করুন।

  1. এখানে আপনার রেফারেন্সের জন্য সম্পূর্ণ RefreshDataWorker ক্লাস আছে:
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
       CoroutineWorker(appContext, params) {

   override suspend fun doWork(): Result {
       val database = getDatabase(applicationContext)
       val repository = VideosRepository(database)
       try {
           repository.refreshVideos()
       } catch (e: HttpException) {
           return Result.retry()
       }
       return Result.success()
   }
}

একজন Worker কাজের একটি ইউনিটকে সংজ্ঞায়িত করে, এবং WorkRequest সংজ্ঞায়িত করে কিভাবে এবং কখন কাজ চালানো উচিত। WorkRequest ক্লাসের দুটি কংক্রিট বাস্তবায়ন রয়েছে:

  • OneTimeWorkRequest ক্লাসটি এক-একটি কাজের জন্য। ( একটি কাজ শুধুমাত্র একবার ঘটে।)
  • PeriodicWorkRequest ক্লাসটি পর্যায়ক্রমিক কাজের জন্য, কাজ যা বিরতিতে পুনরাবৃত্তি হয়।

টাস্ক এক-অফ বা পর্যায়ক্রমিক হতে পারে, তাই সেই অনুযায়ী ক্লাস বেছে নিন। পুনরাবৃত্ত কাজের সময়সূচী সম্পর্কে আরও তথ্যের জন্য, পুনরাবৃত্ত কাজের ডকুমেন্টেশন দেখুন।

এই টাস্কে, আপনি পূর্ববর্তী টাস্কে যে কর্মী তৈরি করেছেন তা চালানোর জন্য আপনি একটি WorkRequest সংজ্ঞায়িত এবং শিডিউল করেন।

ধাপ 1: পুনরাবৃত্ত কাজ সেট আপ করুন

একটি অ্যান্ড্রয়েড অ্যাপের মধ্যে, Application ক্লাস হল বেস ক্লাস যাতে অন্যান্য সমস্ত উপাদান থাকে, যেমন কার্যকলাপ এবং পরিষেবা। যখন আপনার অ্যাপ্লিকেশন বা প্যাকেজের জন্য প্রক্রিয়াটি তৈরি করা হয়, তখন Application ক্লাস (বা Application যেকোনো সাবক্লাস) অন্য কোনো ক্লাসের আগে ইনস্ট্যান্ট করা হয়।

এই নমুনা অ্যাপে, DevByteApplication ক্লাস হল Application ক্লাসের একটি সাবক্লাস। DevByteApplication ক্লাসটি WorkManager নির্ধারণ করার জন্য একটি ভাল জায়গা।

  1. DevByteApplication ক্লাসে, পুনরাবৃত্ত ব্যাকগ্রাউন্ড কাজ সেট আপ করতে setupRecurringWork() নামে একটি পদ্ধতি তৈরি করুন।
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
  1. setupRecurringWork() পদ্ধতির ভিতরে, PeriodicWorkRequestBuilder() পদ্ধতি ব্যবহার করে দিনে একবার চালানোর জন্য একটি পর্যায়ক্রমিক কাজের অনুরোধ তৈরি করুন এবং শুরু করুন। RefreshDataWorker ক্লাসে পাস করুন যা আপনি আগের টাস্কে তৈরি করেছিলেন। টাইম ইউনিটের একটি টাইম ইউনিটের সাথে 1 এর পুনরাবৃত্তি ব্যবধানে পাস TimeUnit. DAYS
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
       .build()

ত্রুটি সমাধান করতে, java.util.concurrent.TimeUnit আমদানি করুন।

ধাপ 2: WorkManager-এর সাথে একটি কাজের অনুরোধের সময় নির্ধারণ করুন

আপনি আপনার WorkRequest সংজ্ঞায়িত করার পরে, আপনি enqueueUniquePeriodicWork() পদ্ধতি ব্যবহার করে WorkManager এর সাথে এটি নির্ধারণ করতে পারেন। এই পদ্ধতিটি আপনাকে সারিতে একটি অনন্যভাবে নামযুক্ত PeriodicWorkRequest যোগ করতে দেয়, যেখানে একটি নির্দিষ্ট নামের শুধুমাত্র একটি PeriodicWorkRequest একবারে সক্রিয় হতে পারে।

উদাহরণস্বরূপ, আপনি শুধুমাত্র একটি সিঙ্ক অপারেশন সক্রিয় করতে চাইতে পারেন৷ যদি একটি সিঙ্ক অপারেশন মুলতুবি থাকে, আপনি একটি ExistingPeriodicWorkPolicy ব্যবহার করে এটিকে চলতে দিতে বা আপনার নতুন কাজের সাথে প্রতিস্থাপন করতে পারেন৷

একটি WorkRequest নির্ধারণ করার উপায় সম্পর্কে আরও জানতে, WorkManager ডকুমেন্টেশন দেখুন।

  1. RefreshDataWorker ক্লাসে, ক্লাসের শুরুতে, একটি সহচর বস্তু যোগ করুন। এই কর্মীকে স্বতন্ত্রভাবে সনাক্ত করতে একটি কাজের নাম সংজ্ঞায়িত করুন।
companion object {
   const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
  1. DevByteApplication ক্লাসে, setupRecurringWork() পদ্ধতির শেষে, setupRecurringWork() enqueueUniquePeriodicWork() ব্যবহার করে কাজের সময় নির্ধারণ করুন। Existing PeriodicWork Policy-এর জন্য KEEP enum-এ পাস করুন। PeriodicWorkRequest প্যারামিটার হিসাবে repeatingRequest পাস করুন।
WorkManager.getInstance().enqueueUniquePeriodicWork(
       RefreshDataWorker.WORK_NAME,
       ExistingPeriodicWorkPolicy.KEEP,
       repeatingRequest)

যদি মুলতুবি (অসমাপ্ত) কাজ একই নামে বিদ্যমান থাকে, তাহলে বিদ্যমান পিরিওডিক ওয়ার্ক পলিসি ExistingPeriodicWorkPolicy. KEEP প্যারামিটার WorkManager পূর্ববর্তী পর্যায়ক্রমিক কাজ রাখতে এবং নতুন কাজের অনুরোধ বাতিল করে দেয়।

  1. DevByteApplication ক্লাসের শুরুতে, একটি CoroutineScope অবজেক্ট তৈরি করুন। Dispatchers.Default পাস করুন। কনস্ট্রাক্টর প্যারামিটার হিসাবে ডিফল্ট।
private val applicationScope = CoroutineScope(Dispatchers.Default)
  1. DevByteApplication ক্লাসে, coroutine শুরু করতে delayedInit() নামে একটি নতুন পদ্ধতি যোগ করুন।
private fun delayedInit() {
   applicationScope.launch {
   }
}
  1. delayedInit() পদ্ধতির ভিতরে, setupRecurringWork( setupRecurringWork() কল করুন।
  2. টিম্বার ইনিশিয়ালাইজেশনটিকে onCreate( onCreate() পদ্ধতি থেকে delayedInit() পদ্ধতিতে সরান।
private fun delayedInit() {
   applicationScope.launch {
       Timber.plant(Timber.DebugTree())
       setupRecurringWork()
   }
}
  1. DevByteApplication ক্লাসে, onCreate onCreate() পদ্ধতির শেষে, delayedInit() পদ্ধতিতে একটি কল যোগ করুন।
override fun onCreate() {
   super.onCreate()
   delayedInit()
}
  1. অ্যান্ড্রয়েড স্টুডিও উইন্ডোর নীচে লগক্যাট ফলকটি খুলুন। RefreshDataWorker এ ফিল্টার করুন।
  2. অ্যাপটি চালান। WorkManager অবিলম্বে আপনার পুনরাবৃত্তি কাজ সময়সূচী.

    Logcat প্যানে, লগ স্টেটমেন্টগুলি লক্ষ্য করুন যা দেখায় যে কাজের অনুরোধটি নির্ধারিত হয়েছে, তারপর সফলভাবে চলে।
D/RefreshDataWorker: Work request for sync is run
I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]

WM-WorkerWrapper লগটি WorkManager লাইব্রেরি থেকে প্রদর্শিত হয়, তাই আপনি এই লগ বার্তাটি পরিবর্তন করতে পারবেন না।

ধাপ 3: (ঐচ্ছিক) একটি ন্যূনতম ব্যবধানের জন্য কাজের অনুরোধের সময়সূচী করুন

এই ধাপে, আপনি সময়ের ব্যবধান 1 দিন থেকে 15 মিনিটে কমিয়ে আনবেন। আপনি এটি করেন যাতে আপনি একটি পর্যায়ক্রমিক কাজের অনুরোধের জন্য লগ দেখতে পারেন।

  1. DevByteApplication ক্লাসে, setupRecurringWork() পদ্ধতির ভিতরে, বর্তমান repeatingRequest সংজ্ঞাটি মন্তব্য করুন। 15 মিনিটের পর্যায়ক্রমিক পুনরাবৃত্তি ব্যবধান সহ একটি নতুন কাজের অনুরোধ যোগ করুন।
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
//        .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
       .build()
  1. অ্যান্ড্রয়েড স্টুডিওতে লগক্যাট প্যানটি খুলুন এবং RefreshDataWorker এ ফিল্টার করুন। পূর্ববর্তী লগগুলি সাফ করতে, সাফ লগক্যাট আইকনে ক্লিক করুন৷ .
  2. অ্যাপটি চালান, এবং WorkManager অবিলম্বে আপনার পুনরাবৃত্ত কাজের সময়সূচী করে। Logcat ফলকে, লগগুলি লক্ষ্য করুন—কাজের অনুরোধ প্রতি 15 মিনিটে একবার চালানো হয়। কাজের অনুরোধ লগের আরেকটি সেট দেখতে 15 মিনিট অপেক্ষা করুন। আপনি অ্যাপ্লিকেশন চলমান ছেড়ে বা এটি বন্ধ করতে পারেন; কাজের ব্যবস্থাপক এখনও চালানো উচিত.

    লক্ষ্য করুন যে ব্যবধান কখনও কখনও 15 মিনিটের কম, এবং কখনও কখনও 15 মিনিটের বেশি। (সঠিক সময় ওএস ব্যাটারি অপ্টিমাইজেশান সাপেক্ষে।)
12:44:40 D/RefreshDataWorker: Work request for sync is run
12:44:40 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
12:59:24 D/RefreshDataWorker: Work request for sync is run
12:59:24 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:15:03 D/RefreshDataWorker: Work request for sync is run
13:15:03 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:29:22 D/RefreshDataWorker: Work request for sync is run
13:29:22 I/WM-WorkerWrapper: Worker result SUCCESS for Work 
13:44:26 D/RefreshDataWorker: Work request for sync is run
13:44:26 I/WM-WorkerWrapper: Worker result SUCCESS for Work
 

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

আপনার পরবর্তী টাস্কে, আপনি সীমাবদ্ধতা যোগ করে এই সমস্যাটির সমাধান করবেন।

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

WorkRequest সংজ্ঞায়িত করার সময়, Worker কখন চালানো উচিত তার জন্য আপনি সীমাবদ্ধতা নির্দিষ্ট করতে পারেন। উদাহরণস্বরূপ, আপনি নির্দিষ্ট করতে চাইতে পারেন যে কাজটি কেবল তখনই চালানো উচিত যখন ডিভাইসটি নিষ্ক্রিয় থাকে, বা শুধুমাত্র যখন ডিভাইসটি প্লাগ ইন করা থাকে এবং Wi-Fi এর সাথে সংযুক্ত থাকে৷ আপনি আবার কাজ করার জন্য একটি ব্যাকঅফ নীতি নির্দিষ্ট করতে পারেন। সমর্থিত সীমাবদ্ধতা হল Constraints.Builder এ সেট করা পদ্ধতি। আরও জানতে, আপনার কাজের অনুরোধের সংজ্ঞা দেখুন।

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

এই ধাপে, আপনি একটি Constraints অবজেক্ট তৈরি করুন এবং অবজেক্টে একটি সীমাবদ্ধতা সেট করুন, একটি নেটওয়ার্ক-টাইপ সীমাবদ্ধতা। (শুধুমাত্র একটি সীমাবদ্ধতার সাথে লগগুলি লক্ষ্য করা সহজ। পরবর্তী ধাপে, আপনি অন্যান্য সীমাবদ্ধতা যোগ করুন।)

  1. DevByteApplication ক্লাসে, setupRecurringWork() এর শুরুতে, Constraints প্রকারের একটি val সংজ্ঞায়িত করুন। Constraints.Builder() পদ্ধতি ব্যবহার করুন।
val constraints = Constraints.Builder()

ত্রুটি সমাধান করতে, androidx.work.Constraints আমদানি করুন।

  1. constraints বস্তুতে একটি নেটওয়ার্ক-টাইপ সীমাবদ্ধতা যোগ করতে setRequiredNetworkType() পদ্ধতি ব্যবহার করুন। UNMETERED ব্যবহার করুন যাতে কাজের অনুরোধটি তখনই চলবে যখন ডিভাইসটি একটি মিটারবিহীন নেটওয়ার্কে থাকে৷
.setRequiredNetworkType(NetworkType.UNMETERED)
  1. বিল্ডার থেকে সীমাবদ্ধতা তৈরি করতে build() পদ্ধতি ব্যবহার করুন।
val constraints = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .build()

এখন আপনাকে কাজের অনুরোধে সদ্য নির্মিত Constraints অবজেক্ট সেট করতে হবে।

  1. DevByteApplication ক্লাসে, setupRecurringWork() পদ্ধতির ভিতরে, পর্যায়ক্রমিক কাজের অনুরোধের জন্য Constraints অবজেক্ট সেট করুন, repeatingRequest । সীমাবদ্ধতা সেট করতে, build() মেথড কলের উপরে setConstraints() মেথড যোগ করুন।
       val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
               .setConstraints(constraints)
               .build()

ধাপ 2: অ্যাপটি চালান এবং লগগুলি লক্ষ্য করুন

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

  1. পূর্বে নির্ধারিত কোনো কাজ বাতিল করতে ডিভাইস বা এমুলেটর থেকে অ্যাপটি আনইনস্টল করুন।
  2. অ্যান্ড্রয়েড স্টুডিওতে লগক্যাট প্যানটি খুলুন। Logcat প্যানে, Clear logcat আইকনে ক্লিক করে আগের লগগুলি সাফ করুন বাম দিকে. work ফিল্টার করুন।
  3. ডিভাইস বা এমুলেটরে Wi-Fi বন্ধ করুন, যাতে আপনি দেখতে পারেন কিভাবে সীমাবদ্ধতা কাজ করে। বর্তমান কোড শুধুমাত্র একটি সীমাবদ্ধতা সেট করে, নির্দেশ করে যে অনুরোধটি শুধুমাত্র একটি মিটারবিহীন নেটওয়ার্কে চালানো উচিত। যেহেতু Wi-Fi বন্ধ আছে, ডিভাইসটি নেটওয়ার্কের সাথে সংযুক্ত নয়, মিটার করা বা আনমিটার করা নেই৷ অতএব, এই সীমাবদ্ধতা পূরণ করা হবে না.
  4. অ্যাপটি চালান এবং Logcat ফলকটি লক্ষ্য করুন। WorkManager অবিলম্বে ব্যাকগ্রাউন্ড টাস্ক নির্ধারণ করে। কারণ নেটওয়ার্কের সীমাবদ্ধতা পূরণ হয় না, কাজটি চালানো হয় না।
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
  1. ডিভাইস বা এমুলেটরে Wi-Fi চালু করুন এবং Logcat ফলকটি দেখুন। এখন নির্ধারিত ব্যাকগ্রাউন্ড টাস্কটি প্রায় প্রতি 15 মিনিটে চালানো হয়, যতক্ষণ না নেটওয়ার্ক সীমাবদ্ধতা পূরণ হয়।
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
11:31:47 D/RefreshDataWorker: Work request for sync is run
11:31:47 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
11:46:45 D/RefreshDataWorker: Work request for sync is run
11:46:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:03:05 D/RefreshDataWorker: Work request for sync is run
12:03:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:16:45 D/RefreshDataWorker: Work request for sync is run
12:16:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:31:45 D/RefreshDataWorker: Work request for sync is run
12:31:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
12:47:05 D/RefreshDataWorker: Work request for sync is run
12:47:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 
13:01:45 D/RefreshDataWorker: Work request for sync is run
13:01:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]

ধাপ 3: আরও সীমাবদ্ধতা যোগ করুন

এই ধাপে, আপনি PeriodicWorkRequest এ নিম্নলিখিত সীমাবদ্ধতাগুলি যোগ করুন:

  • ব্যাটারি কম নয়।
  • ডিভাইস চার্জিং।
  • ডিভাইস নিষ্ক্রিয়; শুধুমাত্র API স্তর 23 (Android M) এবং উচ্চতর ক্ষেত্রে উপলব্ধ।

DevByteApplication ক্লাসে নিম্নলিখিতগুলি প্রয়োগ করুন।

  1. DevByteApplication ক্লাসে, setupRecurringWork() পদ্ধতির ভিতরে, নির্দেশ করে যে ব্যাটারি কম না হলেই কাজের অনুরোধ চালানো উচিত। build() মেথড কলের আগে সীমাবদ্ধতা যোগ করুন এবং setRequiresBatteryNotLow() পদ্ধতি ব্যবহার করুন।
.setRequiresBatteryNotLow(true)
  1. কাজের অনুরোধ আপডেট করুন যাতে ডিভাইসটি চার্জ হওয়ার সময়ই এটি চলে। build() মেথড কলের আগে সীমাবদ্ধতা যোগ করুন এবং setRequiresCharging() পদ্ধতি ব্যবহার করুন।
.setRequiresCharging(true)
  1. কাজের অনুরোধ আপডেট করুন যাতে ডিভাইসটি নিষ্ক্রিয় থাকলেই এটি চলে। build() মেথড কল করার আগে সীমাবদ্ধতা যোগ করুন এবং setRequiresDeviceIdle() পদ্ধতি ব্যবহার করুন। এই সীমাবদ্ধতা শুধুমাত্র তখনই কাজের অনুরোধ চালায় যখন ব্যবহারকারী সক্রিয়ভাবে ডিভাইসটি ব্যবহার করছেন না। এই বৈশিষ্ট্যটি শুধুমাত্র Android 6.0 (Marshmallow) এবং উচ্চতর সংস্করণে উপলব্ধ, তাই SDK সংস্করণ M এবং উচ্চতরের জন্য একটি শর্ত যুক্ত করুন৷
.apply {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       setRequiresDeviceIdle(true)
   }
}

এখানে constraints বস্তুর সম্পূর্ণ সংজ্ঞা।

val constraints = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresBatteryNotLow(true)
       .setRequiresCharging(true)
       .apply {
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
               setRequiresDeviceIdle(true)
           }
       }
       .build()
  1. setupRecurringWork() পদ্ধতির ভিতরে, অনুরোধের ব্যবধানটি দিনে একবারে পরিবর্তন করুন।
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
       .setConstraints(constraints)
       .build()

এখানে একটি লগ সহ setupRecurringWork() পদ্ধতির সম্পূর্ণ বাস্তবায়ন রয়েছে যাতে আপনি কখন পর্যায়ক্রমিক কাজের অনুরোধ নির্ধারিত হয় তা ট্র্যাক করতে পারেন।

private fun setupRecurringWork() {

       val constraints = Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .setRequiresBatteryNotLow(true)
               .setRequiresCharging(true)
               .apply {
                   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                       setRequiresDeviceIdle(true)
                   }
               }
               .build()
       val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
               .setConstraints(constraints)
               .build()
       
       Timber.d("Periodic Work request for sync is scheduled")
       WorkManager.getInstance().enqueueUniquePeriodicWork(
               RefreshDataWorker.WORK_NAME,
               ExistingPeriodicWorkPolicy.KEEP,
               repeatingRequest)
   }
  1. পূর্বে নির্ধারিত কাজের অনুরোধ সরাতে, আপনার ডিভাইস বা এমুলেটর থেকে DevBytes অ্যাপ আনইনস্টল করুন।
  2. অ্যাপটি চালান, এবং WorkManager অবিলম্বে কাজের অনুরোধের সময়সূচী করে। কাজের অনুরোধ দিনে একবার চলে, যখন সমস্ত সীমাবদ্ধতা পূরণ হয়।
  3. এই কাজের অনুরোধটি ব্যাকগ্রাউন্ডে চলবে যতক্ষণ পর্যন্ত অ্যাপটি ইনস্টল থাকবে, এমনকি অ্যাপটি চালু না থাকলেও। সেই কারণে, আপনার ফোন থেকে অ্যাপটি আনইনস্টল করা উচিত।

দারূন কাজ! আপনি DevBytes অ্যাপে প্রতিদিনের প্রি-ফেচ ভিডিওর জন্য একটি ব্যাটারি-বান্ধব কাজের অনুরোধ বাস্তবায়ন এবং শিডিউল করেছেন। WorkManager সিস্টেম রিসোর্স অপ্টিমাইজ করে কাজটি শিডিউল করবে এবং চালাবে। আপনার ব্যবহারকারী এবং তাদের ব্যাটারি খুব খুশি হবে.

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

  • WorkManager API এটিকে স্থগিত করা, অ্যাসিঙ্ক্রোনাস কাজগুলির সময়সূচী করা সহজ করে যেগুলি অবশ্যই নির্ভরযোগ্যভাবে চালানো উচিত।
  • বেশিরভাগ বাস্তব-বিশ্বের অ্যাপ্লিকেশনগুলির দীর্ঘ-চলমান ব্যাকগ্রাউন্ড কাজগুলি সম্পাদন করতে হবে। একটি অপ্টিমাইজ করা এবং দক্ষ উপায়ে একটি ব্যাকগ্রাউন্ড টাস্ক নির্ধারণ করতে, WorkManager ব্যবহার করুন।
  • WorkManager লাইব্রেরির প্রধান ক্লাসগুলি হল Worker , WorkRequest , এবং WorkManager
  • Worker শ্রেণী কাজের একককে প্রতিনিধিত্ব করে। ব্যাকগ্রাউন্ড টাস্ক বাস্তবায়ন করতে, Worker ক্লাস প্রসারিত করুন এবং doWork() পদ্ধতিটি ওভাররাইড করুন।
  • WorkRequest শ্রেণীটি কাজের একটি ইউনিট সঞ্চালনের জন্য একটি অনুরোধের প্রতিনিধিত্ব করে। WorkRequest হল কাজের জন্য পরামিতি নির্দিষ্ট করার জন্য বেস ক্লাস যা আপনি WorkManager এ শিডিউল করেন।
  • WorkRequest ক্লাসের দুটি সুনির্দিষ্ট বাস্তবায়ন রয়েছে: OneTimeWorkRequest ওয়ার্ক রিকোয়েস্ট ওয়ান-অফ টাস্ক এবং PeriodicWorkRequest ওয়ার্ক রিকোয়েস্ট।
  • WorkRequest সংজ্ঞায়িত করার সময়, Worker কখন চালানো উচিত তা নির্দেশ করে আপনি Constraints নির্দিষ্ট করতে পারেন। ডিভাইসটি প্লাগ ইন করা আছে কিনা, ডিভাইসটি নিষ্ক্রিয় কিনা বা Wi-Fi কানেক্ট করা আছে কিনা সেগুলির মতো বিষয়গুলি সীমাবদ্ধতার অন্তর্ভুক্ত।
  • WorkRequest এ সীমাবদ্ধতা যোগ করতে, Constraints.Builder ডকুমেন্টেশনে তালিকাভুক্ত সেট পদ্ধতি ব্যবহার করুন। উদাহরণস্বরূপ, ডিভাইসের ব্যাটারি কম থাকলে WorkRequest চালানো উচিত নয় তা নির্দেশ করার জন্য, setRequiresBatteryNotLow() সেট পদ্ধতি ব্যবহার করুন।
  • আপনি WorkRequest সংজ্ঞায়িত করার পরে, Android সিস্টেমে কাজটি হস্তান্তর করুন৷ এটি করার জন্য, WorkManager enqueue একটি ব্যবহার করে কাজটি নির্ধারণ করুন।
  • Worker কার্যকর করার সঠিক সময় WorkRequest এবং সিস্টেম অপ্টিমাইজেশানে ব্যবহৃত সীমাবদ্ধতার উপর নির্ভর করে। WorkManager এই বিধিনিষেধের পরিপ্রেক্ষিতে সর্বোত্তম সম্ভাব্য আচরণ দেওয়ার জন্য ডিজাইন করা হয়েছে।

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

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

অন্যান্য:

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

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

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

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

প্রশ্ন 1

WorkRequest ক্লাসের কংক্রিট বাস্তবায়ন কি?

OneTimeWorkPeriodicRequest

OneTimeWorkRequest এবং PeriodicWorkRequest কাজের অনুরোধ

OneTimeWorkRequest এবং RecurringWorkRequest

OneTimeOffWorkRequest এবং RecurringWorkRequest

প্রশ্ন 2

API 23 এবং উচ্চতর ব্যাকগ্রাউন্ড টাস্ক শিডিউল করতে WorkManager নিচের কোন ক্লাস ব্যবহার করে?

JobScheduler শুধুমাত্র কাজের সময়সূচী

AlarmManager BroadcastReceiver রিসিভার এবং অ্যালার্ম ম্যানেজার

AlarmManager অ্যালার্ম ম্যানেজার এবং JobScheduler

Scheduler এবং BroadcastReceiver রিসিভার

প্রশ্ন 3

একটি WorkRequest সীমাবদ্ধতা যোগ করতে আপনি কোন API ব্যবহার করেন?

▢ সেট setConstraints()

▢ যোগ addConstraints()

▢ সেট setConstraint()

▢ add addConstraintsToWorkRequest()

পরবর্তী পাঠ শুরু করুন: 10.1 শৈলী এবং থিম

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