यह कोडलैब, Android Kotlin Fundamentals कोर्स का हिस्सा है. अगर कोडलैब को क्रम से पूरा किया जाता है, तो आपको इस कोर्स से सबसे ज़्यादा फ़ायदा मिलेगा. कोर्स के सभी कोडलैब, Android Kotlin Fundamentals कोडलैब के लैंडिंग पेज पर दिए गए हैं.
परिचय
ज़्यादातर ऐप्लिकेशन को लंबे समय तक चलने वाले बैकग्राउंड टास्क करने पड़ते हैं. उदाहरण के लिए, कोई ऐप्लिकेशन सर्वर पर फ़ाइलें अपलोड कर सकता है, सर्वर से डेटा सिंक कर सकता है, और उसे Room
डेटाबेस में सेव कर सकता है. इसके अलावा, वह सर्वर को लॉग भेज सकता है या डेटा पर ज़्यादा संसाधन इस्तेमाल करने वाली कार्रवाइयां कर सकता है. इस तरह की कार्रवाइयां, बैकग्राउंड में यूज़र इंटरफ़ेस (यूआई) थ्रेड (मुख्य थ्रेड) से अलग होनी चाहिए. बैकग्राउंड में चल रहे टास्क, डिवाइस के सीमित संसाधनों का इस्तेमाल करते हैं. जैसे, रैम और बैटरी. अगर इसे सही तरीके से मैनेज नहीं किया जाता है, तो इससे उपयोगकर्ता को खराब अनुभव मिल सकता है.
इस कोडलैब में, आपको WorkManager
का इस्तेमाल करके, बैकग्राउंड टास्क को ऑप्टिमाइज़ और बेहतर तरीके से शेड्यूल करने का तरीका बताया गया है. Android में बैकग्राउंड प्रोसेसिंग के लिए उपलब्ध अन्य समाधानों के बारे में ज़्यादा जानने के लिए, बैकग्राउंड प्रोसेसिंग के बारे में गाइड देखें.
आपको पहले से क्या पता होना चाहिए
- Android आर्किटेक्चर के कॉम्पोनेंट,
ViewModel
,LiveData
, औरRoom
का इस्तेमाल कैसे करें. LiveData
क्लास पर ट्रांसफ़ॉर्मेशन करने का तरीका.- कोरूटीन बनाने और लॉन्च करने का तरीका.
- डेटा बाइंडिंग में बाइंडिंग अडैप्टर का इस्तेमाल कैसे करें.
- रिपॉज़िटरी पैटर्न का इस्तेमाल करके, कैश मेमोरी में सेव किया गया डेटा लोड करने का तरीका.
आपको क्या सीखने को मिलेगा
Worker
बनाने का तरीका, जो काम की एक यूनिट को दिखाता है.- काम करने का अनुरोध करने के लिए,
WorkRequest
बनाने का तरीका. WorkRequest
में constraints जोड़ने का तरीका, ताकि यह तय किया जा सके कि वर्कर को कब और कैसे चलाना है.- बैकग्राउंड में होने वाले टास्क शेड्यूल करने के लिए,
WorkManager
का इस्तेमाल कैसे करें.
आपको क्या करना होगा
- नेटवर्क से DevBytes वीडियो प्लेलिस्ट को पहले से फ़ेच करने के लिए, बैकग्राउंड टास्क को पूरा करने वाला वर्कर बनाएं.
- वर्कर को समय-समय पर चलाने के लिए शेड्यूल करें.
WorkRequest
में कंस्ट्रेंट जोड़ें.- समय-समय पर होने वाले
WorkRequest
को शेड्यूल करें. यह हर दिन एक बार लागू होता है.
इस कोडलैब में, आपको DevBytes ऐप्लिकेशन पर काम करना है. इसे आपने पिछले कोडलैब में बनाया था. (अगर आपके पास यह ऐप्लिकेशन नहीं है, तो इस लेसन के लिए शुरुआती कोड डाउनलोड किया जा सकता है.)
DevBytes ऐप्लिकेशन में, DevByte वीडियो की सूची दिखती है. ये छोटे ट्यूटोरियल, Google की Android डेवलपर रिलेशंस टीम ने बनाए हैं. इन वीडियो में, Android डेवलपमेंट के लिए डेवलपर की सुविधाओं और सबसे सही तरीकों के बारे में बताया गया है.
वीडियो को दिन में एक बार पहले से फ़ेच करके, ऐप्लिकेशन में उपयोगकर्ता अनुभव को बेहतर बनाया जा सकता है. इससे यह पक्का होता है कि उपयोगकर्ता को ऐप्लिकेशन खोलते ही नया कॉन्टेंट मिल जाए.
इस टास्क में, आपको स्टार्टर कोड डाउनलोड करना होगा और उसकी जांच करनी होगी.
पहला चरण: स्टार्टर ऐप्लिकेशन डाउनलोड और रन करना
अगर आपने पिछले कोडलैब में DevBytes ऐप्लिकेशन बनाया है, तो उस पर काम जारी रखा जा सकता है. इसके अलावा, स्टार्टर ऐप्लिकेशन को डाउनलोड भी किया जा सकता है.
इस टास्क में, आपको स्टार्टर ऐप्लिकेशन डाउनलोड करके चलाना होगा. साथ ही, स्टार्टर कोड की जांच करनी होगी.
- अगर आपके पास DevBytes ऐप्लिकेशन पहले से नहीं है, तो GitHub पर मौजूद DevBytesRepository प्रोजेक्ट से, इस कोडलैब के लिए DevBytes का स्टार्टर कोड डाउनलोड करें.
- कोड को अनज़िप करें और Android Studio में प्रोजेक्ट खोलें.
- अगर आपका टेस्ट डिवाइस या एम्युलेटर पहले से इंटरनेट से कनेक्ट नहीं है, तो उसे कनेक्ट करें. ऐप्लिकेशन बनाएं और उसे चलाएं. ऐप्लिकेशन, नेटवर्क से DevByte वीडियो की सूची फ़ेच करता है और उन्हें दिखाता है.
- ऐप्लिकेशन में, किसी वीडियो पर टैप करके उसे YouTube ऐप्लिकेशन में खोलें.
दूसरा चरण: कोड एक्सप्लोर करना
स्टार्टर ऐप्लिकेशन में, पिछले कोडलैब में पेश किया गया बहुत सारा कोड शामिल होता है. इस कोडलैब के स्टार्टर कोड में नेटवर्किंग, यूज़र इंटरफ़ेस, ऑफ़लाइन कैश मेमोरी, और रिपॉज़िटरी मॉड्यूल शामिल हैं. WorkManager
का इस्तेमाल करके, बैकग्राउंड टास्क को शेड्यूल करने पर फ़ोकस किया जा सकता है.
- Android Studio में, सभी पैकेज बड़ा करें.
database
पैकेज एक्सप्लोर करें. इस पैकेज में डेटाबेस की इकाइयां और लोकल डेटाबेस शामिल होता है. इसेRoom
का इस्तेमाल करके लागू किया जाता है.repository
पैकेज एक्सप्लोर करें. इस पैकेज मेंVideosRepository
क्लास होती है, जो डेटा लेयर को बाकी ऐप्लिकेशन से एब्स्ट्रैक्ट करती है.- स्टार्टर कोड के बाकी हिस्से को खुद से एक्सप्लोर करें. इसके लिए, पिछले कोडलैब की मदद लें.
WorkManager
, Android आर्किटेक्चर कॉम्पोनेंट में से एक है. साथ ही, यह Android Jetpack का हिस्सा है. WorkManager
का इस्तेमाल, ऐसे बैकग्राउंड टास्क के लिए किया जाता है जिन्हें बाद में पूरा किया जा सकता है और जिन्हें गारंटी के साथ पूरा करना ज़रूरी होता है:
- टाली जा सकने वाली का मतलब है कि काम को तुरंत पूरा करने की ज़रूरत नहीं है. उदाहरण के लिए, सर्वर को विश्लेषण से जुड़ा डेटा भेजना या बैकग्राउंड में डेटाबेस को सिंक करना, ऐसे काम हैं जिन्हें टाला जा सकता है.
- गारंटी के साथ एक्ज़ीक्यूशन का मतलब है कि ऐप्लिकेशन बंद होने या डिवाइस रीस्टार्ट होने पर भी टास्क चलेगा.
WorkManager
बैकग्राउंड में काम करता है. साथ ही, यह बैटरी और सिस्टम की परफ़ॉर्मेंस को बेहतर बनाने के लिए, सबसे सही तरीकों का इस्तेमाल करता है और यह भी ध्यान रखता है कि ऐप्लिकेशन, डिवाइस के साथ काम करे. WorkManager
, एपीआई लेवल 14 के साथ काम करता है. WorkManager
डिवाइस के एपीआई लेवल के हिसाब से, बैकग्राउंड टास्क को शेड्यूल करने का सही तरीका चुनता है. यह JobScheduler
(एपीआई 23 और उसके बाद के वर्शन पर) या AlarmManager
और BroadcastReceiver
को मिलाकर इस्तेमाल कर सकता है.
WorkManager
की मदद से, यह तय किया जा सकता है कि बैकग्राउंड टास्क कब चलेगा. उदाहरण के लिए, हो सकता है कि आपको टास्क को सिर्फ़ तब चलाना हो, जब बैटरी की स्थिति, नेटवर्क की स्थिति या चार्जिंग की स्थिति कुछ शर्तों को पूरा करती हो. इस कोडलैब में, बाद में आपको कंस्ट्रेंट सेट करने का तरीका बताया जाएगा.
इस कोडलैब में, आपको एक टास्क शेड्यूल करना है. इससे DevBytes वीडियो प्लेलिस्ट को नेटवर्क से दिन में एक बार पहले से फ़ेच किया जा सकेगा. इस टास्क को शेड्यूल करने के लिए, WorkManager
लाइब्रेरी का इस्तेमाल किया जाता है.
build.gradle (Module:app)
फ़ाइल खोलें और प्रोजेक्ट मेंWorkManager
डिपेंडेंसी जोड़ें.
अगर लाइब्रेरी के नए वर्शन का इस्तेमाल किया जाता है, तो समाधान ऐप्लिकेशन को उम्मीद के मुताबिक कंपाइल किया जाना चाहिए. अगर ऐसा नहीं होता है, तो समस्या हल करने की कोशिश करें या लाइब्रेरी के उस वर्शन पर वापस जाएं जो यहां दिखाया गया है.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
- अपने प्रोजेक्ट को सिंक करें और पक्का करें कि कंपाइल करने से जुड़ी कोई गड़बड़ी न हो.
प्रोजेक्ट में कोड जोड़ने से पहले, WorkManager
लाइब्रेरी में मौजूद इन क्लास के बारे में जान लें:
Worker
इस क्लास में, बैकग्राउंड में चलने वाले टास्क को तय किया जाता है. इस क्लास को एक्सटेंड किया जाता है औरdoWork()
तरीके को बदला जाता है.doWork()
तरीके में, बैकग्राउंड में किए जाने वाले कोड को रखा जाता है. जैसे, सर्वर के साथ डेटा सिंक करना या इमेज प्रोसेस करना. इस टास्क मेंWorker
को लागू करें.WorkRequest
यह क्लास, वर्कर को बैकग्राउंड में चलाने के अनुरोध को दिखाती है.WorkRequest
का इस्तेमाल करके, यह कॉन्फ़िगर करें कि वर्कर टास्क कब और कैसे चलाया जाए. इसके लिए,Constraints
का इस्तेमाल करें. जैसे, डिवाइस प्लग इन हो या वाई-फ़ाई से कनेक्ट हो.WorkRequest
को बाद के टास्क में लागू किया जाता है.WorkManager
यह क्लास, आपकेWorkRequest
को शेड्यूल करती है और उसे चलाती है.WorkManager
, वर्क रिक्वेस्ट को इस तरह से शेड्यूल करता है कि सिस्टम के संसाधनों पर लोड कम हो. साथ ही, यह आपके तय किए गए कंस्ट्रेंट का पालन करता है.WorkManager
को बाद के टास्क में लागू किया जाता है.
पहला चरण: वर्कर बनाना
इस टास्क में, बैकग्राउंड में DevBytes वीडियो प्लेलिस्ट को पहले से फ़ेच करने के लिए, Worker
जोड़ा जाता है.
devbyteviewer
पैकेज में,work
नाम का एक नया पैकेज बनाएं.work
पैकेज में,RefreshDataWorker
नाम की नई Kotlin क्लास बनाएं.RefreshDataWorker
क्लास कोCoroutineWorker
क्लास से एक्सटेंड करें. कंस्ट्रक्टर पैरामीटर के तौर परcontext
औरWorkerParameters
पास करें.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}
- ऐब्सट्रैक्ट क्लास की गड़बड़ी को ठीक करने के लिए,
doWork()
क्लास में मौजूदdoWork()
मैथड को बदलें.RefreshDataWorker
override suspend fun doWork(): Result {
return Result.success()
}
सस्पेंडिंग फ़ंक्शन ऐसा फ़ंक्शन होता है जिसे रोका जा सकता है और बाद में फिर से शुरू किया जा सकता है. निलंबित करने वाला फ़ंक्शन, लंबे समय तक चलने वाली कार्रवाई को पूरा कर सकता है. साथ ही, मुख्य थ्रेड को ब्लॉक किए बिना, कार्रवाई के पूरा होने का इंतज़ार कर सकता है.
दूसरा चरण: doWork() को लागू करना
Worker
क्लास में मौजूद doWork()
तरीके को बैकग्राउंड थ्रेड पर कॉल किया जाता है. यह तरीका, काम को सिंक्रोनस तरीके से करता है. साथ ही, इसे ListenableWorker.Result
ऑब्जेक्ट दिखाना चाहिए. Android सिस्टम, Worker
को ज़्यादा से ज़्यादा 10 मिनट देता है, ताकि वह अपना काम पूरा कर सके और ListenableWorker.Result
ऑब्जेक्ट वापस भेज सके. यह समय खत्म होने के बाद, सिस्टम Worker
को बंद कर देता है.
ListenableWorker.Result
ऑब्जेक्ट बनाने के लिए, इनमें से किसी एक स्टैटिक तरीके को कॉल करें. इससे बैकग्राउंड में चल रहे काम के पूरा होने की स्थिति का पता चलता है:
Result.success()
—काम पूरा हो गया है.Result.failure()
—काम पूरा हो गया है, लेकिन हमेशा के लिए गड़बड़ी हुई है.Result.retry()
—काम में कुछ समय के लिए गड़बड़ी हुई है. इसलिए, इसे फिर से आज़माएं.
इस टास्क में, आपको नेटवर्क से DevBytes वीडियो प्लेलिस्ट फ़ेच करने के लिए, doWork()
तरीके को लागू करना होगा. नेटवर्क से डेटा वापस पाने के लिए, VideosRepository
क्लास में मौजूद तरीकों का फिर से इस्तेमाल किया जा सकता है.
RefreshDataWorker
क्लास में,doWork()
के अंदर,VideosDatabase
ऑब्जेक्ट औरVideosRepository
ऑब्जेक्ट बनाएं और इंस्टैंशिएट करें.
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
return Result.success()
}
RefreshDataWorker
क्लास में,doWork()
के अंदर,return
स्टेटमेंट के ऊपर,try
ब्लॉक मेंrefreshVideos()
तरीके को कॉल करें. यह लॉग जोड़ें, ताकि यह ट्रैक किया जा सके कि वर्कर कब चलता है.
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
"अनसुलझा रेफ़रंस" गड़बड़ी को ठीक करने के लिए, retrofit2.HttpException
इंपोर्ट करें.
- आपकी जानकारी के लिए, यहां पूरी
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
को तय करना और शेड्यूल करना होगा, ताकि पिछले टास्क में बनाया गया वर्कर चल सके.
पहला चरण: बार-बार किए जाने वाले काम सेट अप करना
Android ऐप्लिकेशन में, Application
क्लास एक बेस क्लास होती है. इसमें अन्य सभी कॉम्पोनेंट शामिल होते हैं. जैसे, ऐक्टिविटी और सेवाएं. जब आपके ऐप्लिकेशन या पैकेज के लिए प्रोसेस बनाई जाती है, तो Application
क्लास (या Application
की कोई भी सबक्लास) को किसी अन्य क्लास से पहले इंस्टैंशिएट किया जाता है.
इस सैंपल ऐप्लिकेशन में, DevByteApplication
क्लास, Application
क्लास की सबक्लास है. DevByteApplication
क्लास में WorkManager
को शेड्यूल करना सही होता है.
DevByteApplication
क्लास में,setupRecurringWork()
नाम का एक तरीका बनाएं, ताकि बार-बार होने वाले बैकग्राउंड टास्क को सेट अप किया जा सके.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
PeriodicWorkRequestBuilder()
तरीके का इस्तेमाल करके,setupRecurringWork()
तरीके के अंदर, हर दिन में एक बार चलने वाले बार-बार होने वाले काम के अनुरोध को बनाएं और उसे शुरू करें. पिछले टास्क में बनाई गईRefreshDataWorker
क्लास पास करें.TimeUnit.
DAYS
टाइम यूनिट के साथ,1
का दोहराव वाला इंटरवल पास करें.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
इस गड़बड़ी को ठीक करने के लिए, java.util.concurrent.TimeUnit
इंपोर्ट करें.
दूसरा चरण: WorkManager की मदद से WorkRequest शेड्यूल करना
WorkRequest
तय करने के बाद, इसे WorkManager
के साथ शेड्यूल किया जा सकता है. इसके लिए, enqueueUniquePeriodicWork()
तरीके का इस्तेमाल करें. इस तरीके से, आपको एक यूनीक नाम वाला PeriodicWorkRequest
, क्यू में जोड़ने की अनुमति मिलती है. इसमें एक समय में, किसी खास नाम का सिर्फ़ एक PeriodicWorkRequest
चालू हो सकता है.
उदाहरण के लिए, हो सकता है कि आपको सिर्फ़ एक सिंक ऑपरेशन चालू रखना हो. अगर एक सिंक ऑपरेशन पूरा नहीं हुआ है, तो आपके पास उसे पूरा होने देने या ExistingPeriodicWorkPolicy का इस्तेमाल करके, उसे अपने नए काम से बदलने का विकल्प होता है.
WorkRequest
को शेड्यूल करने के तरीकों के बारे में ज़्यादा जानने के लिए, WorkManager
दस्तावेज़ देखें.
RefreshDataWorker
क्लास में, क्लास की शुरुआत में कंपैनियन ऑब्जेक्ट जोड़ें. इस वर्कर की पहचान करने के लिए, कोई यूनीक नाम तय करें.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
DevByteApplication
क्लास में,setupRecurringWork()
तरीके के आखिर में,enqueueUniquePeriodicWork()
तरीके का इस्तेमाल करके काम शेड्यूल करें. ExistingPeriodicWorkPolicy के लिए,KEEP
enum में पास करें.PeriodicWorkRequest
पैरामीटर के तौर परrepeatingRequest
पास करें.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
अगर उसी नाम का कोई ऐसा मौजूदा काम है जो पूरा नहीं (अधूरा) हुआ है, तो ExistingPeriodicWorkPolicy.
KEEP
पैरामीटर की वजह से WorkManager
, बार-बार होने वाले पिछले काम को बनाए रखता है और नए काम के अनुरोध को खारिज कर देता है.
DevByteApplication
क्लास की शुरुआत में,CoroutineScope
ऑब्जेक्ट बनाएं. कंस्ट्रक्टर पैरामीटर के तौर परDispatchers.Default
पास करें.
private val applicationScope = CoroutineScope(Dispatchers.Default)
- कोरूटीन शुरू करने के लिए,
DevByteApplication
क्लास मेंdelayedInit()
नाम का एक नया तरीका जोड़ें.
private fun delayedInit() {
applicationScope.launch {
}
}
delayedInit()
वाले तरीके में,setupRecurringWork()
को कॉल करें.- Timber को शुरू करने की प्रोसेस को
onCreate()
तरीके सेdelayedInit()
तरीके पर ले जाएं.
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
DevByteApplication
क्लास में,onCreate()
तरीके के आखिर में,delayedInit()
तरीके को कॉल करने का तरीका जोड़ें.
override fun onCreate() {
super.onCreate()
delayedInit()
}
- Android Studio विंडो में सबसे नीचे मौजूद, Logcat पैन खोलें.
RefreshDataWorker
पर फ़िल्टर करें. - ऐप्लिकेशन चलाएं.
WorkManager
आपके बार-बार किए जाने वाले काम को तुरंत शेड्यूल कर देता है.
Logcat पैन में, लॉग स्टेटमेंट देखें. इनसे पता चलता है कि वर्क अनुरोध शेड्यूल किया गया है और फिर वह सही तरीके से पूरा हुआ है.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
WM-WorkerWrapper
लॉग, WorkManager
लाइब्रेरी से दिखता है. इसलिए, इस लॉग मैसेज को बदला नहीं जा सकता.
तीसरा चरण: (ज़रूरी नहीं) WorkRequest को कम से कम इंटरवल के लिए शेड्यूल करना
इस चरण में, समयावधि को एक दिन से घटाकर 15 मिनट कर दिया जाता है. ऐसा इसलिए किया जाता है, ताकि बार-बार होने वाले काम के अनुरोध के लॉग देखे जा सकें.
DevByteApplication
क्लास में,setupRecurringWork()
मैथड के अंदर, मौजूदाrepeatingRequest
की परिभाषा को टिप्पणी के तौर पर मार्क करें.15
मिनट के इंटरवल पर बार-बार होने वाले काम के लिए, नया अनुरोध जोड़ें.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
- Android Studio में Logcat पैनल खोलें और
RefreshDataWorker
पर फ़िल्टर करें. पिछले लॉग मिटाने के लिए, Clear logcat आइकॉनपर क्लिक करें .
- ऐप्लिकेशन चलाएं. इसके बाद,
WorkManager
आपके बार-बार किए जाने वाले काम को तुरंत शेड्यूल कर देगा. Logcat पैन में, लॉग देखें. वर्क रिक्वेस्ट को हर 15 मिनट में एक बार चलाया जाता है. काम के अनुरोध से जुड़े लॉग का दूसरा सेट देखने के लिए, 15 मिनट इंतज़ार करें. ऐप्लिकेशन को चालू या बंद किया जा सकता है. हालांकि, WorkManager को चालू रहना चाहिए.
ध्यान दें कि कभी-कभी इंटरवल 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
को कब चलना चाहिए, इस बारे में कंस्ट्रेंट तय किए जा सकते हैं. उदाहरण के लिए, हो सकता है कि आप यह बताना चाहें कि काम सिर्फ़ तभी चलना चाहिए, जब डिवाइस इस्तेमाल में न हो, या सिर्फ़ तब, जब डिवाइस प्लग इन हो और वाई-फ़ाई से कनेक्ट किया हुआ हो. काम को फिर से करने की कोशिश के लिए, बैकऑफ़ नीति भी तय की जा सकती है. Constraints.Builder
में सेट किए गए तरीके, इस्तेमाल की जा सकने वाली पाबंदियां हैं. ज़्यादा जानने के लिए, काम के अनुरोधों को तय करना लेख पढ़ें.
पहला चरण: Constraints ऑब्जेक्ट जोड़ें और एक कंस्ट्रेंट सेट करें
इस चरण में, एक Constraints
ऑब्जेक्ट बनाया जाता है. साथ ही, ऑब्जेक्ट पर एक नेटवर्क-टाइप की पाबंदी सेट की जाती है. (सिर्फ़ एक शर्त होने पर, लॉग को आसानी से देखा जा सकता है. बाद के चरण में, अन्य पाबंदियां जोड़ी जाती हैं.)
DevByteApplication
क्लास में,setupRecurringWork()
की शुरुआत में,Constraints
टाइप काval
तय करें.Constraints.Builder()
तरीके का इस्तेमाल करें.
val constraints = Constraints.Builder()
इस गड़बड़ी को ठीक करने के लिए, androidx.work.Constraints
इंपोर्ट करें.
constraints
ऑब्जेक्ट में नेटवर्क टाइप की पाबंदी जोड़ने के लिए,setRequiredNetworkType()
तरीके का इस्तेमाल करें.UNMETERED
enum का इस्तेमाल करें, ताकि काम का अनुरोध सिर्फ़ तब पूरा हो, जब डिवाइस किसी ऐसे नेटवर्क से कनेक्ट हो जिस पर डेटा के इस्तेमाल की कोई सीमा नहीं है.
.setRequiredNetworkType(NetworkType.UNMETERED)
- बिल्डर से पाबंदियां जनरेट करने के लिए,
build()
तरीके का इस्तेमाल करें.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
अब आपको नई बनाई गई Constraints
ऑब्जेक्ट को वर्क अनुरोध पर सेट करना होगा.
DevByteApplication
क्लास में,setupRecurringWork()
तरीके के अंदर,Constraints
ऑब्जेक्ट को बार-बार होने वाले काम के अनुरोध,repeatingRequest
पर सेट करें. सीमाएं सेट करने के लिए,build()
तरीके के कॉल के ऊपरsetConstraints()
तरीका जोड़ें.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
दूसरा चरण: ऐप्लिकेशन चलाएं और लॉग देखें
इस चरण में, ऐप्लिकेशन को चलाया जाता है. साथ ही, यह देखा जाता है कि बैकग्राउंड में काम करने का अनुरोध, तय समय पर हो रहा है या नहीं.
- पहले से शेड्यूल किए गए किसी भी टास्क को रद्द करने के लिए, डिवाइस या एम्युलेटर से ऐप्लिकेशन को अनइंस्टॉल करें.
- Android Studio में Logcat पैन खोलें. Logcat पैनल में, बाईं ओर मौजूद Logcat मिटाएं आइकॉन
पर क्लिक करके, पिछले लॉग मिटाएं.
work
पर फ़िल्टर करें. - डिवाइस या एम्युलेटर में वाई-फ़ाई बंद करें, ताकि आपको पता चल सके कि पाबंदियां कैसे काम करती हैं. मौजूदा कोड में सिर्फ़ एक शर्त सेट की गई है. इससे पता चलता है कि अनुरोध सिर्फ़ ऐसे नेटवर्क पर चलना चाहिए जिसमें डेटा के इस्तेमाल की कोई सीमा नहीं है. वाई-फ़ाई बंद होने की वजह से, डिवाइस किसी नेटवर्क से कनेक्ट नहीं है. भले ही, वह नेटवर्क मीटर किया गया हो या नहीं. इसलिए, इस शर्त को पूरा नहीं किया जा सकेगा.
- ऐप्लिकेशन चलाएँ और Logcat पैन पर ध्यान दें.
WorkManager
बैकग्राउंड टास्क को तुरंत शेड्यूल करता है. नेटवर्क की ज़रूरी शर्तें पूरी न होने की वजह से, टास्क पूरा नहीं किया जा सका.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- डिवाइस या एम्युलेटर में वाई-फ़ाई चालू करें और 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 [...]
तीसरा चरण: और पाबंदियां जोड़ना
इस चरण में, PeriodicWorkRequest
में ये पाबंदियां जोड़ी जाती हैं:
- बैटरी का लेवल कम नहीं है.
- डिवाइस को चार्ज करना.
- डिवाइस का इस्तेमाल नहीं किया जा रहा है; यह सुविधा सिर्फ़ एपीआई लेवल 23 (Android M) और इसके बाद के वर्शन में उपलब्ध है.
DevByteApplication
क्लास में यहां दी गई जानकारी लागू करें.
DevByteApplication
क्लास में,setupRecurringWork()
तरीके के अंदर यह बताएं कि वर्क रिक्वेस्ट सिर्फ़ तब चलनी चाहिए, जब बैटरी का लेवल कम न हो.build()
तरीके को कॉल करने से पहले, कंस्ट्रेंट जोड़ें औरsetRequiresBatteryNotLow()
तरीके का इस्तेमाल करें.
.setRequiresBatteryNotLow(true)
- काम के अनुरोध को अपडेट करें, ताकि यह सिर्फ़ तब चले, जब डिवाइस चार्ज हो रहा हो.
build()
तरीके को कॉल करने से पहले, कंस्ट्रेंट जोड़ें औरsetRequiresCharging()
तरीके का इस्तेमाल करें.
.setRequiresCharging(true)
- काम के अनुरोध को अपडेट करें, ताकि यह सिर्फ़ तब चले, जब डिवाइस का इस्तेमाल न किया जा रहा हो.
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()
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)
}
- पहले से शेड्यूल की गई काम से जुड़ी अनुरोध को हटाने के लिए, अपने डिवाइस या एम्युलेटर से DevBytes ऐप्लिकेशन को अनइंस्टॉल करें.
- ऐप्लिकेशन चलाएं. इसके बाद,
WorkManager
तुरंत काम के अनुरोध को शेड्यूल कर देता है. सभी कंस्ट्रेंट को पूरा करने पर, काम का अनुरोध दिन में एक बार चलता है. - यह टास्क, बैकग्राउंड में तब तक चलता रहेगा, जब तक ऐप्लिकेशन इंस्टॉल है. भले ही, ऐप्लिकेशन न चल रहा हो. इसलिए, आपको अपने फ़ोन से ऐप्लिकेशन को अनइंस्टॉल कर देना चाहिए.
बहुत बढ़िया! आपने DevBytes ऐप्लिकेशन में वीडियो को हर दिन पहले से फ़ेच करने के लिए, बैटरी के हिसाब से काम करने वाले अनुरोध को लागू किया और शेड्यूल किया. WorkManager
सिस्टम के संसाधनों को ऑप्टिमाइज़ करके, काम को शेड्यूल और पूरा करेगा. आपके उपयोगकर्ताओं और उनकी बैटरी को बहुत खुशी मिलेगी.
Android Studio प्रोजेक्ट: DevBytesWorkManager.
WorkManager
एपीआई की मदद से, ऐसे एसिंक्रोनस टास्क को आसानी से शेड्यूल किया जा सकता है जिन्हें बाद में पूरा किया जा सकता है. साथ ही, यह भी पक्का किया जा सकता है कि वे टास्क भरोसेमंद तरीके से पूरे हों.- ज़्यादातर ऐप्लिकेशन को लंबे समय तक चलने वाले बैकग्राउंड टास्क करने पड़ते हैं. बैकग्राउंड टास्क को ऑप्टिमाइज़ और बेहतर तरीके से शेड्यूल करने के लिए,
WorkManager
का इस्तेमाल करें. WorkManager
लाइब्रेरी में मुख्य क्लासWorker
,WorkRequest
, औरWorkManager
हैं.Worker
क्लास, काम की एक यूनिट को दिखाता है. बैकग्राउंड टास्क लागू करने के लिए,Worker
क्लास को बढ़ाएं औरdoWork()
तरीके को बदलें.WorkRequest
क्लास, काम की एक यूनिट को पूरा करने के अनुरोध को दिखाती है.WorkRequest
,WorkManager
में शेड्यूल किए गए काम के लिए पैरामीटर तय करने वाली बेस क्लास है.WorkRequest
क्लास को दो तरीके से लागू किया जा सकता है:OneTimeWorkRequest
का इस्तेमाल एक बार किए जाने वाले टास्क के लिए किया जाता है औरPeriodicWorkRequest
का इस्तेमाल बार-बार होने वाले काम के अनुरोधों के लिए किया जाता है.WorkRequest
तय करते समय,Constraints
तय किया जा सकता है. इससे यह पता चलता है किWorker
कब चलना चाहिए. पाबंदियों में ये चीज़ें शामिल होती हैं: डिवाइस प्लग इन है या नहीं, डिवाइस इस्तेमाल में नहीं है या नहीं या वाई-फ़ाई कनेक्ट है या नहीं.WorkRequest
में शर्तें जोड़ने के लिए,Constraints.Builder
के दस्तावेज़ में दिए गए सेट तरीकों का इस्तेमाल करें. उदाहरण के लिए, अगर आपको यह बताना है कि डिवाइस की बैटरी कम होने परWorkRequest
नहीं चलना चाहिए, तोsetRequiresBatteryNotLow()
सेट करने के तरीके का इस्तेमाल करें.WorkRequest
को तय करने के बाद, टास्क को Android सिस्टम को सौंप दें. इसके लिए,WorkManager
enqueue
तरीकों में से किसी एक का इस्तेमाल करके, टास्क को शेड्यूल करें.Worker
को एक्ज़ीक्यूट किए जाने का सटीक समय,WorkRequest
में इस्तेमाल किए गए कंस्ट्रेंट और सिस्टम के ऑप्टिमाइज़ेशन पर निर्भर करता है.WorkManager
को इन पाबंदियों को ध्यान में रखकर, सबसे अच्छा परफ़ॉर्म करने के लिए डिज़ाइन किया गया है.
Udacity का कोर्स:
Android डेवलपर का दस्तावेज़:
- काम से जुड़े अनुरोधों के बारे में बताना
WorkManager
- WorkManager का इस्तेमाल शुरू करना
- बार-बार होने वाला काम
- बैकग्राउंड में प्रोसेस करने के बारे में गाइड
अन्य:
इस सेक्शन में, उन छात्र-छात्राओं के लिए होमवर्क असाइनमेंट की सूची दी गई है जो किसी शिक्षक के कोर्स के हिस्से के तौर पर इस कोडलैब पर काम कर रहे हैं. शिक्षक के पास ये विकल्प होते हैं:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को बताएं कि होमवर्क असाइनमेंट कैसे सबमिट किए जाते हैं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल अपनी ज़रूरत के हिसाब से कर सकते हैं. साथ ही, वे चाहें, तो कोई दूसरा होमवर्क भी दे सकते हैं.
अगर आपको यह कोडलैब खुद से पूरा करना है, तो अपनी जानकारी की जांच करने के लिए, इन होमवर्क असाइनमेंट का इस्तेमाल करें.
पहला सवाल
WorkRequest
क्लास को लागू करने के कौन-कौनसे तरीके हैं?
▢ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest
और PeriodicWorkRequest
▢ OneTimeWorkRequest
और RecurringWorkRequest
▢ OneTimeOffWorkRequest
और RecurringWorkRequest
दूसरा सवाल
एपीआई 23 और उसके बाद के वर्शन पर बैकग्राउंड टास्क को शेड्यूल करने के लिए, WorkManager
इनमें से किस क्लास का इस्तेमाल करता है?
▢ सिर्फ़ JobScheduler
▢ BroadcastReceiver
और AlarmManager
▢ AlarmManager
और JobScheduler
▢ Scheduler
और BroadcastReceiver
तीसरा सवाल
WorkRequest
में पाबंदियां जोड़ने के लिए, किस एपीआई का इस्तेमाल किया जाता है?
▢ setConstraints()
▢ addConstraints()
▢ setConstraint()
▢ addConstraintsToWorkRequest()
अगला लेसन शुरू करें:
इस कोर्स में मौजूद अन्य कोडलैब के लिंक के लिए, Android Kotlin Fundamentals कोडलैब का लैंडिंग पेज देखें.