कोरूटीन एक ऐसा डिज़ाइन पैटर्न है जिसे कई चीज़ों के साथ इस्तेमाल किया जा सकता है. Android, एसिंक्रोनस रूप से एक्ज़ीक्यूट होने वाले कोड को आसान बनाने के लिए काम करता है. कोरूटीन जिन्हें वर्शन 1.3 में Kotlin में जोड़ा गया था. साथ ही, इन्हें जानने के लिए भी किया जा सकता है.
Android पर, कोरूटीन लंबे समय तक चलने वाले उन टास्क को मैनेज करने में मदद करते हैं जो ऐसा न हो, तो मुख्य थ्रेड को ब्लॉक करें और ऐप्लिकेशन का इस्तेमाल बंद कर दें. कोरूटीन इस्तेमाल करने वाले 50% से ज़्यादा पेशेवर डेवलपर ने अपनी उत्पादकता बढ़ाई. इस विषय में बताया गया है कि इन समस्याओं को ठीक करने के लिए, Kotlin कोरूटीन का इस्तेमाल कैसे किया जा सकता है की समस्या देता है, जिससे आप ज़्यादा साफ़ और कम शब्दों वाला ऐप्लिकेशन कोड लिख सकते हैं.
सुविधाएं
एसिंक्रोनस प्रोग्रामिंग के लिए, कोरूटीन हमारा सुझाव है: Android. ध्यान देने लायक सुविधाओं में ये शामिल हैं:
- लाइटवेट: एक ही थ्रेड पर कई कोरूटीन चलाए जा सकते हैं, क्योंकि के लिए सहायता निलंबन, जो उस थ्रेड को ब्लॉक नहीं करता जहां कोरूटीन चल रहा है. निलंबित यह एक साथ कई कार्रवाइयां करने के साथ-साथ, ब्लॉक करने की तुलना में मेमोरी सेव करता है.
- कम मेमोरी लीक: इसका इस्तेमाल करें स्ट्रक्चर्ड एक साथ कई काम करना स्कोप के अंदर कार्रवाइयां करने के लिए.
- रद्द करने की पहले से मौजूद सहायता: रद्द करने की प्रोसेस यह प्रोसेस, कोरूटीन की मौजूदा हैरारकी की मदद से अपने-आप लागू होती है.
- Jetpack इंटिग्रेशन: कई Jetpack लाइब्रेरी में ऐसे एक्सटेंशन जो कोरूटीन के साथ काम करते हैं. कुछ सूचनाएं मिल रही हैं लाइब्रेरी में अलग-अलग कोरूटीन स्कोप में एक्सपोर्ट किया जा सकता है, एक साथ कई काम करने के लिए इस्तेमाल किया जाता है.
उदाहरण के तौर पर दी गई खास जानकारी
ऐप्लिकेशन के आर्किटेक्चर की गाइड के आधार पर, दिए गए उदाहरण इस विषय में नेटवर्क के लिए अनुरोध करके, नतीजे को मुख्य साइट पर वापस भेजना थ्रेड जिसमें ऐप्लिकेशन उपयोगकर्ता को नतीजा दिखा सकता है.
खास तौर पर, ViewModel
आर्किटेक्चर कॉम्पोनेंट, मुख्य थ्रेड पर रिपॉज़िटरी लेयर को कॉल करता है
नेटवर्क अनुरोध को ट्रिगर कर सकता है. यह गाइड अलग-अलग तरह के समाधान के बारे में बताती है
जो मुख्य थ्रेड को अनब्लॉक करने के लिए कोरूटीन का इस्तेमाल करती हैं.
ViewModel
में KTX एक्सटेंशन का एक सेट शामिल है जो सीधे तौर पर इनके साथ काम करता है
कोरूटीन. ये एक्सटेंशन
lifecycle-viewmodel-ktx
लाइब्रेरी और इसे इस्तेमाल किया गया है
देखें.
डिपेंडेंसी की जानकारी
अपने Android प्रोजेक्ट में कोरूटीन इस्तेमाल करने के लिए, ये डिपेंडेंसी जोड़ें
ऐप्लिकेशन की build.gradle
फ़ाइल में:
ग्रूवी
dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' }
Kotlin
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9") }
बैकग्राउंड थ्रेड में एक्ज़ीक्यूट किया जा रहा है
मुख्य थ्रेड पर नेटवर्क अनुरोध करने पर, इंतज़ार करना पड़ सकता है या ब्लॉक किया जा सकता है.
जब तक उसे कोई प्रतिक्रिया न मिल जाए. थ्रेड को ब्लॉक करने की वजह से, ओएस काम नहीं कर रहा है
onDraw()
को कॉल कर पाएगा. इससे आपका ऐप्लिकेशन फ़्रीज़ हो सकता है और हो सकता है
ऐप्लिकेशन नॉट रिस्पॉन्डिंग (ANR) डायलॉग पर ले जाता है. बेहतर उपयोगकर्ता के लिए
अनुभव है, तो आइए इस कार्रवाई को बैकग्राउंड थ्रेड पर चलाते हैं.
आइए, सबसे पहले Repository
की हमारी क्लास देखते हैं और जानते हैं कि यह कैसा है
नेटवर्क के लिए अनुरोध किया जा रहा है:
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
class LoginRepository(private val responseParser: LoginResponseParser) {
private const val loginUrl = "https://example.com/login"
// Function that makes the network request, blocking the current thread
fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
val url = URL(loginUrl)
(url.openConnection() as? HttpURLConnection)?.run {
requestMethod = "POST"
setRequestProperty("Content-Type", "application/json; utf-8")
setRequestProperty("Accept", "application/json")
doOutput = true
outputStream.write(jsonBody.toByteArray())
return Result.Success(responseParser.parse(inputStream))
}
return Result.Error(Exception("Cannot open HttpURLConnection"))
}
}
makeLoginRequest
सिंक्रोनस है और कॉल थ्रेड को ब्लॉक करता है. मॉडल को
नेटवर्क अनुरोध की प्रतिक्रिया के बाद, हमारी अपनी Result
क्लास है.
जब उपयोगकर्ता क्लिक करता है, तब ViewModel
नेटवर्क अनुरोध ट्रिगर करता है
उदाहरण के लिए, किसी बटन पर:
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
loginRepository.makeLoginRequest(jsonBody)
}
}
पिछले कोड का इस्तेमाल करके, LoginViewModel
यूज़र इंटरफ़ेस (यूआई) थ्रेड को ब्लॉक कर रहा है, जब
नेटवर्क अनुरोध कर रहा है. निष्पादन को स्थानांतरित करने का सबसे आसान समाधान
मुख्य थ्रेड को बंद किया जाता है. यह एक नया कोरूटीन बनाना और नेटवर्क को एक्ज़ीक्यूट करना होता है
I/O थ्रेड के लिए अनुरोध:
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
// Create a new coroutine to move the execution off the UI thread
viewModelScope.launch(Dispatchers.IO) {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
loginRepository.makeLoginRequest(jsonBody)
}
}
}
आइए, login
फ़ंक्शन में कोरूटीन कोड को देखते हैं:
viewModelScope
, पहले से तयCoroutineScope
है, जो इसके साथ शामिल हैViewModel
KTX एक्सटेंशन. ध्यान दें कि सभी कोरूटीन दायरा.CoroutineScope
, एक या इससे ज़्यादा कोरूटीन मैनेज करता है.launch
एक ऐसा फ़ंक्शन है जो कोरूटीन बनाता है और संबंधित डिस्पैचर को उसके फ़ंक्शन को एक्ज़ीक्यूट करना.Dispatchers.IO
बताता है कि इस कोरूटीन को I/O कार्रवाइयों के लिए रिज़र्व किया गया थ्रेड.
login
फ़ंक्शन को इस तरह से एक्ज़ीक्यूट किया जाता है:
- ऐप्लिकेशन, मुख्य थ्रेड पर मौजूद
View
लेयर सेlogin
फ़ंक्शन को कॉल करता है. launch
एक नया कोरूटीन बनाता है और नेटवर्क के लिए अनुरोध करता है स्वतंत्र रूप से I/O कार्रवाइयों के लिए रिज़र्व किए गए थ्रेड पर.- कोरूटीन चलने के दौरान,
login
फ़ंक्शन एक्ज़ीक्यूशन करता रहता है और शायद वापस भेज दिया जाए. ध्यान दें कि आसानी के लिए, नेटवर्क रिस्पॉन्स को फ़िलहाल अनदेखा कर दिया जाता है.
इस कोरूटीन को viewModelScope
से शुरू किया गया है. इसलिए, इसे
ViewModel
का स्कोप. अगर ViewModel
को बंद कर दिया जाता है, क्योंकि
उपयोगकर्ता, स्क्रीन से दूर नेविगेट कर रहा है, viewModelScope
अपने-आप
रद्द कर दिया जाता है और सभी चल रहे कोरूटीन रद्द कर दिए जाते हैं.
पिछले उदाहरण में एक समस्या यह है कि अगर
एक्ज़ीक्यूशन को साफ़ तौर पर बंद करने के लिए makeLoginRequest
को याद रखने की ज़रूरत है
मुख्य थ्रेड. आइए, देखते हैं कि हम हल करने के लिए, Repository
में किस तरह बदलाव कर सकते हैं
इस समस्या को हल कर लिया है.
मुख्य तौर पर सुरक्षा के लिए कोरूटीन इस्तेमाल करना
हम फ़ंक्शन को मुख्य तौर पर सुरक्षित मानते हैं. ऐसा तब होता है, जब वह
मुख्य थ्रेड. कॉल करने की सुविधा के तौर पर, makeLoginRequest
फ़ंक्शन मुख्य तौर पर सुरक्षित नहीं है
मुख्य थ्रेड का makeLoginRequest
यूज़र इंटरफ़ेस (यूआई) को ब्लॉक करता है. इसका इस्तेमाल करें
एक्ज़ीक्यूशन को आगे बढ़ाने के लिए, कोरूटीन लाइब्रेरी से withContext()
फ़ंक्शन
कोरूटीन को किसी दूसरे थ्रेड में भेजा जाता है:
class LoginRepository(...) {
...
suspend fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
// Move the execution of the coroutine to the I/O dispatcher
return withContext(Dispatchers.IO) {
// Blocking network request code
}
}
}
withContext(Dispatchers.IO)
, कोरूटीन के एक्ज़ीक्यूशन को
I/O थ्रेड, जो हमारे कॉलिंग फ़ंक्शन को मुख्य-सुरक्षित बनाता है और यूज़र इंटरफ़ेस (यूआई) को इन कामों के लिए चालू करता है
उन्हें अपडेट करें.
makeLoginRequest
पर suspend
कीवर्ड का निशान भी लगाया गया है. यह कीवर्ड
यह Kotlin का तरीका है, जिससे कोरूटीन के अंदर से कॉल किए जाने वाले फ़ंक्शन को लागू किया जाता है.
इस उदाहरण में, कोरूटीन LoginViewModel
में बनाया गया है.
जब makeLoginRequest
, एक्ज़ीक्यूशन को मुख्य थ्रेड से बाहर ले जाता है, तो कोरूटीन को
login
फ़ंक्शन को अब मुख्य थ्रेड में एक्ज़ीक्यूट किया जा सकता है:
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
// Create a new coroutine on the UI thread
viewModelScope.launch {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
// Make the network call and suspend execution until it finishes
val result = loginRepository.makeLoginRequest(jsonBody)
// Display result of the network request to the user
when (result) {
is Result.Success<LoginResponse> -> // Happy path
else -> // Show error in UI
}
}
}
}
ध्यान दें कि यहां कोरूटीन की अब भी ज़रूरत है, क्योंकि makeLoginRequest
suspend
फ़ंक्शन का इस्तेमाल करने के साथ-साथ सभी suspend
फ़ंक्शन को
एक कोरूटीन.
यह कोड पिछले login
उदाहरण से कई मायनों में अलग है:
launch
,Dispatchers.IO
पैरामीटर नहीं लेता है. अगर आपको लालच नहीं चाहिए, तोlaunch
कोDispatcher
पास करते हैं, तो यहां से लॉन्च किए गए कोरूटीनviewModelScope
मुख्य थ्रेड में चलता है.- नेटवर्क अनुरोध के नतीजे को, अब सफलता दिखाने के लिए मैनेज किया जाता है या गड़बड़ी वाला यूज़र इंटरफ़ेस (यूआई) शामिल करें.
लॉगिन फ़ंक्शन अब इस तरह से काम करता है:
- ऐप्लिकेशन, मुख्य थ्रेड पर मौजूद
View
लेयर सेlogin()
फ़ंक्शन को कॉल करता है. launch
, मुख्य थ्रेड पर एक नया कोरूटीन बनाता है और कोरूटीन शुरू हो जाता है लागू करता है.- कोरूटीन में,
loginRepository.makeLoginRequest()
को किया गया कॉल अबwithContext
तक कोरूटीन को चलाने का काम निलंबित किया जाएगाmakeLoginRequest()
में ब्लॉक चल रहा है. withContext
ब्लॉक पूरा होने के बाद,login()
में कोरूटीन फिर से चालू हो जाता है नेटवर्क अनुरोध के नतीजे के साथ मुख्य थ्रेड पर एक्ज़ीक्यूशन करेगा.
हैंडलिंग से जुड़े अपवाद
उन अपवादों को मैनेज करने के लिए जो Repository
लेयर थ्रो कर सकता है, Kotlin के
अपवादों के लिए पहले से मौजूद सहायता.
इस उदाहरण में, हमने try-catch
ब्लॉक का इस्तेमाल किया है:
class LoginViewModel(
private val loginRepository: LoginRepository
): ViewModel() {
fun login(username: String, token: String) {
viewModelScope.launch {
val jsonBody = "{ username: \"$username\", token: \"$token\"}"
val result = try {
loginRepository.makeLoginRequest(jsonBody)
} catch(e: Exception) {
Result.Error(Exception("Network request failed"))
}
when (result) {
is Result.Success<LoginResponse> -> // Happy path
else -> // Show error in UI
}
}
}
}
इस उदाहरण में, makeLoginRequest()
की ओर से दिया गया कोई भी ऐसा अपवाद
कॉल को यूज़र इंटरफ़ेस (यूआई) में किसी गड़बड़ी के तौर पर हैंडल किया जाता है.
कोरूटीन के अतिरिक्त संसाधन
Android पर कोरूटीन के बारे में ज़्यादा जानकारी के लिए, यह देखें Kotlin कोरूटीन की मदद से, ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाएं.
कोरूटीन से जुड़े और संसाधनों के लिए, ये लिंक देखें:
- Coroutines की खास जानकारी (JetBrains)
- Coroutines गाइड (JetBrains)
- Kotlin कोरूटीन और फ़्लो के लिए अतिरिक्त संसाधन