कोटलिन में जितने अधिक मैंने कॉटआउट पर रिपोर्ट पढ़ी और देखी, उतने ही मैंने इस भाषा उपकरण की प्रशंसा की। उनकी स्थिर रिलीज हाल ही में कोटलिन 1.3 में जारी की गई थी, जिसका अर्थ है कि यह गोता शुरू करने और मेरे मौजूदा RxJava कोड का उपयोग करके एक उदाहरण के रूप में कार्रवाई करने का प्रयास करने का समय है। इस पोस्ट में, हम इस बात पर ध्यान केंद्रित करेंगे कि मौजूदा नेटवर्क अनुरोधों को कैसे लिया जाए और उन्हें RxJava को कोरटाइन के साथ बदलकर परिवर्तित किया जाए।

सच कहूँ तो, इससे पहले कि मैं कोरटाइन की कोशिश करता, मुझे लगा कि वे पहले जो थे उससे बहुत अलग थे। हालाँकि, कोरुटिन के मूल सिद्धांत में वही अवधारणाएं शामिल हैं जिनका उपयोग हम RxJava प्रतिक्रियाशील प्रवाह में करते हैं। एक उदाहरण के रूप में, आइए मेरे एक एप्लिकेशन से नेटवर्क अनुरोध बनाने के लिए एक सरल RxJava कॉन्फ़िगरेशन लें:
- Rx एडेप्टर ( retrofit2: adapter-rxjava2 ) का उपयोग कर रेट्रोफिट के लिए नेटवर्क इंटरफेस को परिभाषित करें। कार्य एक Rx ढांचे से वस्तुओं को लौटाएंगे, जैसे एकल या अवलोकनीय । (कार्य यहां उपयोग किए जाते हैं और विधियाँ नहीं, क्योंकि यह माना जाता है कि पुराना कोड कोटलिन में भी लिखा गया था। खैर, या एंड्रॉइड स्टूडियो के माध्यम से जावा से परिवर्तित किया गया है)।
- हम दूसरे वर्ग से एक निश्चित कार्य कहते हैं (उदाहरण के लिए, एक भंडार, या गतिविधि)।
- हम उन थ्रेड्स के लिए निर्धारित करते हैं, जिस पर वे शेड्यूलर को निष्पादित किया जाएगा और परिणाम (तरीके .subscribeOn) और (.observeOn () ) वापस करेंगे।
- हम बिना लिंक के ऑब्जेक्ट के लिंक को सेव करते हैं (उदाहरण के लिए, CompiteObservable में)।
- घटनाओं की धारा के लिए सदस्यता लें।
- गतिविधि जीवन चक्र की घटनाओं के आधार पर धारा से सदस्यता समाप्त करें।
यह आरएक्स के साथ काम करने के लिए मूल एल्गोरिथ्म है (मैपिंग कार्यों को ध्यान में नहीं रखना और अन्य डेटा जोड़तोड़ का विवरण)। कोरुटिन के लिए, सिद्धांत बहुत ज्यादा नहीं बदलता है। एक ही अवधारणा, केवल शब्दावली बदल रही है।
- हम coroutine के लिए एडेप्टर का उपयोग करके रेट्रोफिट के लिए नेटवर्क इंटरफेस को परिभाषित करते हैं। कार्य Corutin API से आस्थगित ऑब्जेक्ट लौटाएगा।
- हम इन कार्यों को दूसरे वर्ग से कहते हैं (उदाहरण के लिए, एक भंडार, या गतिविधि)। एकमात्र अंतर: प्रत्येक फ़ंक्शन को निलंबित के रूप में चिह्नित किया जाना चाहिए।
- उस डिस्पैचर को परिभाषित करें जिसका उपयोग कोरटाइन के लिए किया जाएगा।
- हम जॉब ऑब्जेक्ट के लिंक को अनसब्सक्राइब करने के लिए सेव करते हैं।
- किसी भी तरह से संभव हो कोरटाइन चलाएं।
- हम गतिविधि जीवन चक्र की घटनाओं के आधार पर कॉरआउट को रद्द करते हैं।
जैसा कि आप उपरोक्त अनुक्रमों से देख सकते हैं, आरएक्स और कोरुटिन की निष्पादन प्रक्रिया बहुत समान है। यदि हम कार्यान्वयन के विवरण को ध्यान में नहीं रखते हैं, तो इसका मतलब है कि हम अपने पास दृष्टिकोण को बनाए रख सकते हैं - हम केवल कुछ चीजों को प्रतिस्थापित करते हैं ताकि हमारे कार्यान्वयन को कोरटाइन-अनुकूल बनाया जा सके।

पहला कदम जो हमें उठाना चाहिए वह है रिट्रोफिट को आस्थगित वस्तुओं को वापस करने की अनुमति देना। आस्थगित वस्तु गैर-अवरुद्ध वायदा है जो यदि आवश्यक हो तो पूर्ववत किया जा सकता है। ये वस्तुएं मूल रूप से एक कॉरआउट नौकरी हैं, जिसमें संबंधित नौकरी के लिए मूल्य शामिल है। Deferred प्रकार का उपयोग करने से हमें अय्यूब के समान विचार मिलाने की अनुमति मिलती है, अतिरिक्त सफलता प्राप्त करने की विफलता या असफलता - जैसे कि यह नेटवर्क अनुरोधों के लिए आदर्श बनाता है।
यदि आप RxJava के साथ Retrofit का उपयोग कर रहे हैं, तो आप शायद RxJava Call Adapter Factory का उपयोग कर रहे हैं। सौभाग्य से, जेक वोर्टन ने उसे कोरटाइन के समकक्ष लिखा।
हम इस कॉल अडैप्टर का उपयोग रेट्रोफिट बिल्डर में कर सकते हैं, और फिर उसी तरह से हमारे रिट्रोफिट इंटरफेस को आरजेबीजे के साथ लागू कर सकते हैं:
private fun makeService(okHttpClient: OkHttpClient): MyService { val retrofit = Retrofit.Builder() .baseUrl("some_api") .client(okHttpClient) .addCallAdapterFactory(CoroutineCallAdapterFactory()) .build() return retrofit.create(MyService::class.java) }
अब आइए MyService इंटरफ़ेस को देखें, जिसका उपयोग ऊपर किया गया है। हमें रिट्रोफिट इंटरफ़ेस में डीफ़र्ड के साथ लौटे ऑब्ज़र्वेबल प्रकारों को बदलना होगा। यदि यह इस तरह हुआ करता था:
@GET("some_endpoint") fun getData(): Observable<List<MyData>>
अब हम इसे इसके साथ प्रतिस्थापित करते हैं:
@GET("some_endpoint") fun getData(): Deferred<List<MyData>>
जब भी हम getData () कहते हैं, तो आस्थगित वस्तु हमारे पास वापस आ जाएगी - नेटवर्क अनुरोधों के लिए नौकरी का एक एनालॉग। पहले, हमने किसी तरह इस फ़ंक्शन को RxJava के साथ बुलाया:
override fun getData(): Observable<List<MyData>> { return myService.getData() .map { result -> result.map { myDataMapper.mapFromRemote(it) } } }
इस RxJava स्ट्रीम में, हम अपने यूटिलिटी फंक्शन को कॉल करते हैं, फिर RxJava API से मैप ऑपरेशन लागू करते हैं और बाद में यूआई लेयर में इस्तेमाल होने वाली किसी चीज़ के लिए रिक्वेस्ट से वापस किए गए डेटा की मैपिंग करते हैं। जब हम कोरटाइन के साथ कार्यान्वयन का उपयोग करते हैं तो यह थोड़ा बदल जाएगा। शुरुआत के लिए, फ़ंक्शन के शरीर के अंदर एक आलसी ऑपरेशन करने के लिए, हमारे फ़ंक्शन को निलंबित (स्थगित) होना चाहिए। और इसके लिए, कॉलिंग फ़ंक्शन को भी स्थगित करना होगा। आस्थगित फ़ंक्शन गैर-अवरुद्ध है, और इसे शुरू में कहा जाने के बाद इसे नियंत्रित किया जा सकता है। आप इसे शुरू कर सकते हैं, इसे रोक सकते हैं, इसे फिर से शुरू या रद्द कर सकते हैं।
override suspend fun getData(): List<MyData> { ... }
अब हमें अपनी उपयोगिता फ़ंक्शन को कॉल करना होगा। पहली नज़र में, हम एक ही काम कर रहे हैं, लेकिन हमें यह याद रखना चाहिए कि अब हम ऑब्जर्वेबल के बजाय डिफर्ड हो गए हैं।
override suspend fun getData(): List<MyData> { val result = myService.getData() ... }
इस बदलाव के कारण, हम अब RxJava API से मैप ऑपरेशन चेन का उपयोग नहीं कर सकते हैं। और इस बिंदु पर भी, डेटा हमारे लिए उपलब्ध नहीं है - हमारे पास केवल एक आस्थगित उदाहरण है। अब हमें क्वेरी के परिणाम की प्रतीक्षा करने के लिए प्रतीक्षा () फ़ंक्शन का उपयोग करना चाहिए और फिर फ़ंक्शन के अंदर कोड निष्पादित करना जारी रखना चाहिए:
override suspend fun getData(): List<MyData> { val result = myService.getData().await() ... }
इस बिंदु पर, हमें पूर्ण अनुरोध और उपयोग के लिए उपलब्ध डेटा मिलता है। इसलिए, अब हम मैपिंग ऑपरेशन कर सकते हैं:
override suspend fun getData(): List<MyData> { val result = myService.getData().await() return result.map { myDataMapper.mapFromRemote(it) } }
हमने कॉलिंग क्लास और इस्तेमाल किए गए कॉरआउट्स के साथ अपना रेट्रोफिट इंटरफ़ेस लिया। अब हम अपनी गतिविधि या टुकड़ों से इस कोड को कॉल करना चाहते हैं और उस डेटा का उपयोग करते हैं जो हमें नेटवर्क से मिला है।
हमारी गतिविधि में, हम अय्यूब के लिए एक लिंक बनाकर शुरू करेंगे, जिसमें हम अपने coroutine संचालन को असाइन कर सकते हैं और फिर इसे नियंत्रित करने के लिए उपयोग कर सकते हैं, उदाहरण के लिए, onDestroy () कॉल के दौरान अनुरोध रद्द करना।
private var myJob: Job? = null override fun onDestroy() { myJob?.cancel() super.onDestroy() }
अब हम myJob वैरिएबल को कुछ असाइन कर सकते हैं। आइए हमारे अनुरोध को coroutines के साथ देखें:
myJob = CoroutineScope(Dispatchers.IO).launch { val result = repo.getLeagues() withContext(Dispatchers.Main) { //do something with result } }
इस पोस्ट में, मैं डिस्प्यूटर्स में कटौती नहीं करना चाहूंगा या कोरटाइन के भीतर ऑपरेशन करना नहीं चाहूंगा, क्योंकि यह अन्य पदों के लिए एक विषय है। संक्षेप में, यहां क्या होता है:
- एक पैरामीटर के रूप में IO डिस्पैचर का उपयोग करके एक CoroutineScope उदाहरण बनाएं। इस डिस्पैचर का उपयोग अवरुद्ध आई / ओ संचालन करने के लिए किया जाता है, जैसे कि नेटवर्क अनुरोध।
- हम लॉन्च फ़ंक्शन के साथ अपना कोरआउट शुरू करते हैं - यह फ़ंक्शन एक नया कोरआउट लॉन्च करता है और टाइप जॉब के एक चर के लिए एक लिंक देता है।
- फिर हम नेटवर्क रिक्वेस्ट करके डेटा प्राप्त करने के लिए अपने रिपॉजिटरी के लिंक का उपयोग करते हैं।
- अंत में, हम यूआई थ्रेड पर काम करने के लिए मुख्य डिस्पैचर का उपयोग करते हैं। यहां हम प्राप्त डेटा को उपयोगकर्ताओं को दिखा सकते हैं।
अगली पोस्ट में, लेखक विवरण में थोड़ा गहरा खुदाई करने का वादा करता है, लेकिन वर्तमान सामग्री को कोरटाइन्स का अध्ययन शुरू करने के लिए पर्याप्त होना चाहिए।
इस पोस्ट में, हमने Corutin API से Deferred ऑब्जेक्ट्स के साथ Retrofit प्रतिक्रियाओं के RxJava कार्यान्वयन को बदल दिया। हम नेटवर्क से डेटा प्राप्त करने के लिए इन कार्यों को कहते हैं, और फिर उन्हें अपनी गतिविधि में प्रदर्शित करते हैं। मुझे आशा है कि आपने देखा कि कोरटाइन के साथ शुरुआत करने के लिए आपको कितने बदलाव करने की आवश्यकता है, और एपीआई की सादगी की सराहना की, खासकर जब पढ़ना और लिखना कोड।
मूल पोस्ट पर टिप्पणियों में, मुझे एक पारंपरिक अनुरोध मिला: पूरे कोड को दिखाएं। इसलिए, मैंने एक साधारण एप्लिकेशन बनाया, जो स्टार्टअप पर, यैंडेक्स के साथ ट्रेनों का शेड्यूल प्राप्त करता है। शेड्यूल एपीआई और इसे रिसाइक्लरव्यू में प्रदर्शित करता है। लिंक: https://github.com/AndreySBer/RetrofitCoroutinesExample
मैं यह भी जोड़ना चाहूंगा कि कोरटाइन्स RxJava के लिए एक अवर प्रतिस्थापन प्रतीत होते हैं, क्योंकि वे थ्रेड्स को सिंक्रनाइज़ करने के लिए ऑपरेशन के बराबर सेट की पेशकश नहीं करते हैं। इस संबंध में, यह Kotlin : RxKotlin के लिए ReactiveX कार्यान्वयन को देखने लायक है।
यदि आप Android Jetpack का उपयोग करते हैं, तो मुझे Retrofit, coroutines, LiveData और MVVM के साथ एक उदाहरण मिला: https://codinginfinite.com/kotlin-coroutine-call-adapter-retrofit/