यह कोडलैब Android Kotlin के बुनियादी कोर्स में शामिल है. अगर आप कोडलैब के क्रम में काम करते हैं, तो आपको इस कोर्स का ज़्यादा से ज़्यादा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Android Kotlin से जुड़े बेसिक कोडलैब के लैंडिंग पेज पर दिए गए हैं.
परिचय
असल दुनिया के ज़्यादातर ऐप्लिकेशन को लंबे समय तक बैकग्राउंड में चलने वाले टास्क करने होते हैं. उदाहरण के लिए, कोई ऐप्लिकेशन सर्वर पर फ़ाइलें अपलोड कर सकता है, सर्वर से डेटा सिंक कर सकता है, और उसे Room
डेटाबेस में सेव कर सकता है, सर्वर पर लॉग भेज सकता है या डेटा पर महंगे ऑपरेशन कर सकता है. इस तरह की कार्रवाइयां बैकग्राउंड में, यूज़र इंटरफ़ेस (यूआई) थ्रेड से (मुख्य थ्रेड) बंद करनी चाहिए. बैकग्राउंड टास्क, डिवाइस के रैम और बैटरी जैसे सीमित संसाधनों का इस्तेमाल करते हैं. अगर सही तरीके से इस्तेमाल न करने पर उपयोगकर्ता को खराब अनुभव मिल सकता है.
इस कोडलैब में, आप WorkManager
इस्तेमाल करने का तरीका जान सकते हैं. इससे, आप बैकग्राउंड टास्क को ऑप्टिमाइज़ करने और उसे बेहतर तरीके से शेड्यूल करने में मदद पा सकते हैं. Android में बैकग्राउंड प्रोसेसिंग के लिए उपलब्ध दूसरे तरीकों के बारे में ज़्यादा जानने के लिए, बैकग्राउंड प्रोसेसिंग के लिए गाइड देखें.
आपको क्या पता होना चाहिए
ViewModel
,LiveData
, औरRoom
Android आर्किटेक्चर के कॉम्पोनेंट को इस्तेमाल करने का तरीका.LiveData
कक्षा में बदलाव करने का तरीका.- कोरूटीन बनाने और लॉन्च करने का तरीका.
- डेटा बाइंडिंग में बाइंडिंग अडैप्टर का इस्तेमाल कैसे करें.
- रिपॉज़िटरी पैटर्न का इस्तेमाल करके, कैश मेमोरी में सेव किए गए डेटा को कैसे लोड करें.
आप इन चीज़ों के बारे में जानेंगे
- काम की इकाई दिखाने वाला
Worker
बनाने का तरीका. - काम पूरा करने के लिए,
WorkRequest
बनाने का तरीका. - यह तय करने के लिए कि किसी वर्कर को कब और कैसे चलाना है,
WorkRequest
में सीमाएं कैसे जोड़ें. - बैकग्राउंड टास्क को शेड्यूल करने के लिए,
WorkManager
का इस्तेमाल कैसे करें.
आप क्या कर पाएंगे!
- नेटवर्क से DevBytes वीडियो प्लेलिस्ट को पहले से फ़ेच करने के लिए किसी बैकग्राउंड टास्क को लागू करने के लिए एक वर्कर बनाएं.
- समय-समय पर चलाने के लिए वर्कर को शेड्यूल करें.
WorkRequest
में कंस्ट्रेंट जोड़ें.- समय-समय पर शुरू होने वाला ऐसा
WorkRequest
शेड्यूल करें जिसे दिन में एक बार चलाया जाता है.
इस कोडलैब में, आप DevBytes ऐप्लिकेशन पर काम करते हैं, जिसे आपने पिछले कोडलैब में बनाया था. (अगर आपके पास यह ऐप्लिकेशन नहीं है, तो आप इस लेसन के लिए स्टार्टर कोड डाउनलोड कर सकते हैं.)
DevBytes ऐप्लिकेशन, DevByte वीडियो की एक सूची दिखाता है, जो Google Android डेवलपर रिलेशन टीम के बनाए गए छोटे ट्यूटोरियल हैं. वीडियो में Android डेवलपमेंट के लिए डेवलपर सुविधाओं और सबसे सही तरीकों के बारे में बताया गया है.
ऐप्लिकेशन में उपयोगकर्ता के अनुभव को बेहतर बनाने के लिए, उन वीडियो को दिन में एक बार फ़ेच किया जाता है. इससे यह पक्का होता है कि ऐप्लिकेशन खोलते ही उपयोगकर्ता को नया कॉन्टेंट मिल जाए.
इस टास्क में, आप स्टार्टर कोड डाउनलोड करेंगे और उसकी जांच करेंगे.
पहला चरण: स्टार्टर ऐप्लिकेशन डाउनलोड करना और चलाना
आप पिछले कोडलैब (अगर आपके पास है) में बनाए गए DevBytes ऐप्लिकेशन का इस्तेमाल करके, काम करना जारी रख सकते हैं. इसके अलावा, स्टार्टर ऐप्लिकेशन डाउनलोड किया जा सकता है.
इस टास्क में, आप स्टार्टर ऐप्लिकेशन डाउनलोड करके चलाते हैं और स्टार्टर कोड की जांच करते हैं.
- अगर आपके पास पहले से DevBytes ऐप्लिकेशन नहीं है, तो इस कोडलैब के लिए, DevBytes स्टार्टर कोड को GitHub से DevBytesRepository प्रोजेक्ट से डाउनलोड करें.
- कोड को अनज़िप करें और प्रोजेक्ट को Android Studio में खोलें.
- अगर आपका टेस्ट डिवाइस या एम्युलेटर पहले से कनेक्ट नहीं है, तो इसे इंटरनेट से कनेक्ट करें. ऐप्लिकेशन बनाएं और चलाएं. ऐप्लिकेशन, नेटवर्क से DevByte वीडियो की सूची फ़ेच करता है और उन्हें दिखाता है.
- ऐप्लिकेशन में किसी भी वीडियो पर टैप करके उसे YouTube ऐप्लिकेशन में खोलें.
दूसरा चरण: कोड के बारे में जानना
स्टार्टर ऐप्लिकेशन में कई कोड होते हैं, जिन्हें पिछले कोडलैब में पेश किया गया था. इस कोडलैब के स्टार्टर कोड में नेटवर्किंग, इंटरफ़ेस, ऑफ़लाइन कैश, और रिपॉज़िटरी मॉड्यूल हैं. आप WorkManager
का इस्तेमाल करके, बैकग्राउंड टास्क को शेड्यूल करने पर ध्यान दे सकते हैं.
- Android Studio में, सभी पैकेज को बड़ा करें.
database
पैकेज के बारे में और जानें. पैकेज में डेटाबेस इकाइयां और स्थानीय डेटाबेस शामिल हैं, जिन्हेंRoom
का उपयोग करके लागू किया जाता है.repository
पैकेज के बारे में और जानें. पैकेज मेंVideosRepository
क्लास होती है, जो डेटा लेयर को बाकी ऐप्लिकेशन से एब्स्ट्रैक्ट करती है.- पिछले कोडलैब की मदद से, बाकी के स्टार्टर कोड को खुद एक्सप्लोर करें.
WorkManager
, Android आर्किटेक्चर कॉम्पोनेंट में से एक है और यह Android Jetpack का हिस्सा है. WorkManager
, बैकग्राउंड काम के लिए है जिसे #39:
- टाले जा सकने वाले का मतलब है कि काम को तुरंत चलाना ज़रूरी नहीं है. उदाहरण के लिए, सर्वर को विश्लेषण करने वाला डेटा भेजना या बैकग्राउंड में डेटाबेस सिंक करना, काम का नहीं है.
- गारंटी के तौर पर एक्ज़ीक्यूशन का मतलब है कि ऐप्लिकेशन बाहर निकलने या डिवाइस के रीस्टार्ट होने पर भी टास्क चलेगा.
हालांकि, WorkManager
बैकग्राउंड के काम करते हैं, लेकिन इनके साथ काम करने से जुड़ी समस्याओं और बैटरी और सिस्टम की परफ़ॉर्मेंस के लिए सबसे सही तरीकों का ध्यान रखा जाता है. WorkManager
, वापस API लेवल 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
यह क्लास, वर्कर को बैकग्राउंड में चलाने का अनुरोध दिखाती है.Constraints
की मदद से, वर्कर काम को कब और कैसे चलाना है, यह कॉन्फ़िगर करने के लिएWorkRequest
का इस्तेमाल करें. जैसे, डिवाइस प्लग-इन करना या वाई-फ़ाई से कनेक्ट करना. आप बाद के टास्क मेंWorkRequest
लागू करते हैं.WorkManager
यह कक्षा आपकेWorkRequest
को शेड्यूल करती और चलाती है.WorkManager
, काम के अनुरोधों को इस तरह शेड्यूल करता है कि आपकी तरफ़ से तय की गई पाबंदियों का पालन करते हुए, सिस्टम के संसाधनों पर लोड फैलता है. आप बाद के टास्क मेंWorkManager
लागू करते हैं.
पहला चरण: वर्कर बनाना
इस टास्क में, DevBytes वीडियो की प्लेलिस्ट को पहले से फ़ेच करने के लिए, Worker
को बैकग्राउंड में जोड़ें.
devbyteviewer
पैकेज में,work
नाम का एक नया पैकेज बनाएं.work
पैकेज के अंदर,RefreshDataWorker
नाम की एक नई Kotlin क्लास बनाएं.CoroutineWorker
क्लास सेRefreshDataWorker
क्लास को बढ़ाएं.context
औरWorkerParameters
को कंस्ट्रक्टर पैरामीटर के तौर पर पास करें.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}
- ऐब्स्ट्रैक्ट क्लास से जुड़ी गड़बड़ी को ठीक करने के लिए,
RefreshDataWorker
क्लास मेंdoWork()
मेथड को बदलें.
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() {
}
setupRecurringWork()
तरीके में, समय-समय पर काम से जुड़ा अनुरोध बनाएं और शुरू करें. यह अनुरोधPeriodicWorkRequestBuilder()
वाले तरीके से, दिन में एक बार किया जा सकता है.RefreshDataWorker
की उस क्लास को पास करें जिसे आपने पिछले टास्क में बनाया था.TimeUnit.
DAYS
की समय इकाई के साथ,1
के दोहराव वाले इंटरवल में पास हों.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
गड़बड़ी को ठीक करने के लिए, java.util.concurrent.TimeUnit
इंपोर्ट करें.
दूसरा चरण: WorkManager के साथ WorkRequest शेड्यूल करना
WorkRequest
को तय करने के बाद, आप enqueueUniquePeriodicWork()
वाले तरीके से इसे WorkManager
के साथ शेड्यूल कर सकते हैं. इस तरीके से आप सूची में खास नाम PeriodicWorkRequest
जोड़ सकते हैं, जहां किसी खास नाम का सिर्फ़ एक PeriodicWorkRequest
चालू हो सकता है.
उदाहरण के लिए, हो सकता है कि आप सिंक करने की सिर्फ़ एक कार्रवाई चालू करना चाहें. अगर सिंक करने की एक कार्रवाई 'मंज़ूरी मिलना बाकी है' के तौर पर होती है, तो आप currentPeriodicWorkPolicy का इस्तेमाल करके, उसे चलाने दें या नए काम से बदलने दें.
WorkRequest
शेड्यूल करने के तरीकों के बारे में ज़्यादा जानने के लिए, WorkManager
दस्तावेज़ देखें.
RefreshDataWorker
क्लास में, क्लास की शुरुआत में, कंपैनियन ऑब्जेक्ट जोड़ें. इस वर्कर की पहचान खास तरीके से करने के लिए, किसी काम का नाम तय करें.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
DevByteApplication
क्लास में,setupRecurringWork()
तरीके के आखिर में,enqueueUniquePeriodicWork()
तरीके का इस्तेमाल करके काम को शेड्यूल करें. ExistingPeriodicWorkPolicy के लिएKEEP
enum में पास करें.repeatingRequest
कोPeriodicWorkRequest
पैरामीटर के तौर पर पास करें.
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()
को कॉल करें.- टिंबर शुरू करने के तरीके को
onCreate()
तरीके सेdelayedInit()
तरीके में ले जाएं.
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
DevByteApplication
क्लास में,onCreate()
तरीके के आखिर में,delayedInit()
तरीके में कॉल जोड़ें.
override fun onCreate() {
super.onCreate()
delayedInit()
}
- Android Studio विंडो में सबसे नीचे मौजूद लॉगकैट पैनल खोलें.
RefreshDataWorker
पर फ़िल्टर करें. - ऐप्लिकेशन चलाएं.
WorkManager
आपके बार-बार होने वाले काम को तुरंत शेड्यूल कर देता है.
लॉगकैट पैनल में, उन लॉग स्टेटमेंट पर ध्यान दें जो बताते हैं कि काम का अनुरोध शेड्यूल किया गया है और उसके बाद चलता है.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
WM-WorkerWrapper
लॉग WorkManager
लाइब्रेरी से दिखाया जाता है, इसलिए आप यह लॉग संदेश बदल नहीं सकते.
तीसरा चरण: (ज़रूरी नहीं) कम से कम इंटरवल के लिए, WorkRequest को शेड्यूल करना
इस कदम में, आप समय अंतराल को 1 दिन से घटाकर 15 मिनट कर देते हैं. आप ऐसा इसलिए करते हैं, ताकि आपको समय-समय पर काम करने के अनुरोध को लॉग में दिखाया जा सके.
DevByteApplication
क्लास में,setupRecurringWork()
तरीके में, मौजूदाrepeatingRequest
की परिभाषा के बारे में बताएं. समय-समय पर15
मिनट का दोहराव वाला नया अनुरोध जोड़ें.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
- Android Studio में लॉगकैट पैनल खोलें और
RefreshDataWorker
पर फ़िल्टर करें. पिछले लॉग मिटाने के लिए, लॉगकैट हटाएं आइकॉन पर क्लिक करें.
- ऐप्लिकेशन चलाएं और
WorkManager
के ज़रिए आपके बार-बार होने वाले काम को तुरंत शेड्यूल कर दिया जाता है. लॉगकैट पैनल में, लॉग पर ध्यान दें—काम का अनुरोध हर 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
के चलने की अवधि तय कर सकते हैं. उदाहरण के लिए, हो सकता है कि आप यह बताना चाहें कि काम सिर्फ़ तभी चलना चाहिए, जब डिवाइस इस्तेमाल में न हो, या सिर्फ़ तब, जब डिवाइस प्लग इन हो और वाई-फ़ाई से कनेक्ट किया हुआ हो. आप फिर से कोशिश करने के लिए, बैकऑफ़ नीति भी तय कर सकते हैं. इस्तेमाल किए जा सकने वाले कंस्ट्रेंट, Constraints.Builder
में सेट किए गए तरीके होते हैं. ज़्यादा जानने के लिए, काम से जुड़े आपके अनुरोध तय करना देखें.
पहला चरण: एक कंस्ट्रेंट ऑब्जेक्ट जोड़ें और एक कंस्ट्रेंट सेट करें
इस चरण में, आप एक Constraints
ऑब्जेक्ट बनाते हैं और ऑब्जेक्ट पर एक कंस्ट्रेंट सेट करते हैं, जो कि नेटवर्क टाइप का कंस्ट्रेंट होता है. {0}इस लॉग में सिर्फ़ एक कंस्ट्रेंट के साथ ध्यान रखना आसान होता है. बाद के चरण में, आप अन्य कंस्ट्रेंट जोड़ते हैं.)
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()
तरीके के अंदर, समय-समय पर काम करने के अनुरोध,repeatingRequest
परConstraints
ऑब्जेक्ट सेट करें. कंस्ट्रेंट सेट करने के लिए,build()
मेथड के ऊपरsetConstraints()
मैथड जोड़ें.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
दूसरा चरण: ऐप्लिकेशन चलाना और लॉग पर ध्यान देना
इस चरण में, आप ऐप्लिकेशन चलाते हैं और बैकग्राउंड में समय-समय पर बैकग्राउंड में चल रहे काम के अनुरोध को देखते हैं.
- पहले से शेड्यूल किए गए किसी भी टास्क को रद्द करने के लिए, ऐप्लिकेशन को डिवाइस या एम्युलेटर से अनइंस्टॉल करें.
- Android Studio में Logcat पैनल खोलें. Logcat पैनल में, बाईं ओर मौजूद लॉगकैट हटाएं आइकॉन
पर क्लिक करके, पिछले लॉग मिटाएं.
work
पर फ़िल्टर करें. - डिवाइस या एम्युलेटर में वाई-फ़ाई बंद करें, ताकि आप देख सकें कि कंस्ट्रेंट कैसे काम करते हैं. मौजूदा कोड सिर्फ़ एक कंस्ट्रेंट सेट करता है, जो यह बताता है कि अनुरोध सिर्फ़ ऐसे नेटवर्क पर चलाया जाना चाहिए जिसे सीमित नहीं किया गया है. वाई-फ़ाई बंद होने की वजह से, डिवाइस नेटवर्क से कनेक्ट नहीं है, सीमित या सीमित डेटा वाला नेटवर्क नहीं है. इसलिए, इस सीमा को पूरा नहीं किया जाएगा.
- ऐप्लिकेशन चलाएं और लॉगकैट पैनल देखें.
WorkManager
बैकग्राउंड टास्क को तुरंत शेड्यूल करता है. नेटवर्क में रुकावट नहीं होने की वजह से यह टास्क नहीं चल सकता.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- डिवाइस या एम्युलेटर में वाई-फ़ाई चालू करें और लॉगकैट पैनल देखें. अब शेड्यूल किए गए बैकग्राउंड टास्क को हर 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
को बेहतरीन व्यवहार देने के लिए डिज़ाइन किया गया है.
Udcity कोर्स:
Android डेवलपर दस्तावेज़:
- काम से जुड़े आपके अनुरोध की परिभाषा तय करना
WorkManager
- WorkManager का इस्तेमाल शुरू करना
- बार-बार होने वाला काम
- बैकग्राउंड प्रोसेसिंग के लिए गाइड
अन्य:
इस सेक्शन में उन छात्र-छात्राओं के लिए गृहकार्य की असाइनमेंट की सूची दी गई है जो इस कोडलैब के ज़रिए एक शिक्षक की देखरेख में कोर्स में काम कर रहे हैं. यह क्रिएटर का काम #33 पर निर्भर करता है:
- अगर ज़रूरी हो, तो होमवर्क असाइन करें.
- छात्र-छात्राओं को होमवर्क के असाइनमेंट सबमिट करने के तरीके के बारे में बताएं.
- होमवर्क असाइनमेंट को ग्रेड दें.
शिक्षक इन सुझावों का इस्तेमाल जितनी चाहें उतनी कम या ज़्यादा कर सकते हैं. साथ ही, उन्हें अपने हिसाब से कोई भी होमवर्क असाइन करना चाहिए.
अगर आप इस कोडलैब के ज़रिए खुद काम कर रहे हैं, तो बेझिझक इन होमवर्क असाइनमेंट का इस्तेमाल करें.
पहला सवाल
WorkRequest
क्लास को कंक्रीट तरीके से लागू करने का क्या तरीका है?
▢ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest
और PeriodicWorkRequest
▢ OneTimeWorkRequest
और RecurringWorkRequest
▢ OneTimeOffWorkRequest
और RecurringWorkRequest
दूसरा सवाल
एपीआई 23 और उसके बाद के वर्शन पर, बैकग्राउंड टास्क को शेड्यूल करने के लिए, WorkManager
इनमें से कौनसी क्लास का इस्तेमाल करता है?
▢ सिर्फ़ JobScheduler
है
▢ BroadcastReceiver
और AlarmManager
▢ AlarmManager
और JobScheduler
▢ Scheduler
और BroadcastReceiver
तीसरा सवाल
WorkRequest
में कंस्ट्रेंट जोड़ने के लिए किस एपीआई का इस्तेमाल किया जाता है?
▢ setConstraints()
▢ addConstraints()
▢ setConstraint()
▢ addConstraintsToWorkRequest()
अगले लेसन पर जाएं:
इस कोर्स में दिए गए दूसरे कोडलैब के लिंक के लिए, Android Kotlin की बुनियादी बातें कोडलैब का लैंडिंग पेज देखें.