Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
💾 Data, Network और Architecture  ·  Lesson 32

Android में Kotlin Coroutines

Coroutines क्यों?

Android screen को main thread पर draw करता है। वहाँ database load या API call करें तो app अटक जाती है; ~5 seconds बाद Android "App isn't responding" (ANR) दिखाता है। Coroutines background काम को normal ऊपर-से-नीचे code में लिखने देती हैं — बिना callbacks।

Main thread block

  • Main पर Thread.sleep / network
  • UI अटका, taps काम नहीं करते
  • ANR dialog

Coroutine

  • suspend fun loadNotes()
  • इंतज़ार में thread free
  • UI smooth, result बाद में
Block किए बिना इंतज़ार

suspend functions और launch

ये examples plain Kotlin हैं और outputs असली हैं। App में runBlocking की जगह viewModelScope use करेंगे।

Kotlin
import kotlinx.coroutines.*

suspend fun loadNotes(): List<String> {
    delay(1000)                       // pretend database / network work
    return listOf("Maths homework", "Physics notes")
}

fun main() = runBlocking {
    println("1. Start (thread: main)")
    val job = launch {
        val notes = loadNotes()       // suspends, does NOT block the thread
        println("3. Loaded ${notes.size} notes")
    }
    println("2. UI is still free while loading…")
    job.join()
    println("4. Done")
}
1. Start (thread: main) 2. UI is still free while loading… 3. Loaded 2 notes 4. Done
Main threadCoroutinelaunch { }"2. UI is still free" printdelay(1000) – suspended, thread freeresult तैयार → "3. Loaded 2 notes"
Suspended coroutine thread नहीं घेरती

async से parallel काम

Kotlin
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

suspend fun getProfile(): String { delay(1000); return "Riya" }
suspend fun getMarks(): Int { delay(1000); return 92 }

fun main() = runBlocking {
    val sequential = measureTimeMillis {
        val p = getProfile(); val m = getMarks()
        println("Sequential: $p $m")
    }
    val parallel = measureTimeMillis {
        val p = async { getProfile() }
        val m = async { getMarks() }
        println("Parallel: ${p.await()} ${m.await()}")
    }
    println("sequential ≈ ${sequential / 1000}s, parallel ≈ ${parallel / 1000}s")
}
Sequential: Riya 92 Parallel: Riya 92 sequential ≈ 2s, parallel ≈ 1s

Dispatchers और withContext

Dispatcherकिसके लिए
Dispatchers.MainViews update करना (viewModelScope / lifecycleScope में default)
Dispatchers.IOFiles, plain JDBC/SQLite, blocking network libraries
Dispatchers.DefaultCPU-heavy काम: बड़ी lists sort, parsing, image processing
Kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    val result = withContext(Dispatchers.Default) {     // heavy CPU work off the main thread
        (1..1_000_000).sumOf { it.toLong() }
    }
    println("Sum = $result")

    try {
        withTimeout(500) { delay(2000); println("never printed") }
    } catch (e: TimeoutCancellationException) {
        println("Timed out after 500 ms")
    }

    val job = launch { repeat(10) { i -> println("tick $i"); delay(300) } }
    delay(700)
    job.cancel()                                      // like leaving the screen
    println("Cancelled: ${job.isCancelled}")
}
Sum = 500000500000 Timed out after 500 ms tick 0 tick 1 tick 2 Cancelled: true

Android scopes

Kotlin
// ViewModel – cancelled automatically when the ViewModel is cleared
class NoteViewModel(app: Application) : AndroidViewModel(app) {
    fun save(note: Note) = viewModelScope.launch {
        repo.save(note)                 // Room suspend function
    }
}

// Fragment / Activity – cancelled when the lifecycle is destroyed
viewLifecycleOwner.lifecycleScope.launch {
    val note = viewModel.getNote(id)    // suspend
    binding.etTitle.setText(note?.title)
}

// Collect a Flow only while the screen is visible
viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.results.collect { adapter.submitList(it) }
    }
}
viewModelScopeViewModel जितना जीता है (rotation में बचता)lifecycleScope / viewLifecycleOwner.lifecycleScopeActivity / fragment view जितना जीता हैGlobalScopeकभी cancel नहीं — बचें
काम जितनी देर चलना चाहिए उसी हिसाब से scope चुनें

Timeouts और cancellation

जब scope cancel होता है (user screen छोड़ता है), उसकी सारी coroutines अगले suspension point पर रुक जाती हैं — कोई leak नहीं, मरे views को update नहीं। withTimeout धीमा काम रोकता है।

Errors handle करना

Kotlin – Student Diary NoteViewModel.loadTip()
viewModelScope.launch {
    _tip.value = TipState.Loading
    _tip.value = try {
        val tips = TipsApi.service.getTips().tips          // may throw IOException / HttpException
        TipState.Success(tips.random())
    } catch (e: Exception) {
        TipState.Error(e.message ?: "Network error")
    }
}

Student Diary का असली example

Kotlin
// AddEditNoteFragment – copy the picked photo on a background thread
private fun copyImage(uri: Uri) {
    viewLifecycleOwner.lifecycleScope.launch {
        val path = withContext(Dispatchers.IO) {                 // file work → IO thread
            ImageStore.copyToAppStorage(requireContext(), uri)
        }
        if (path == null) toast(R.string.image_error) else { imagePath = path; showImage() }  // back on Main
    }
}

// ReminderWorker – WorkManager's CoroutineWorker runs doWork() as a suspend function
override suspend fun doWork(): Result {
    val note = AppDatabase.get(applicationContext).noteDao().getById(noteId) ?: return Result.success()
    NotificationHelper.show(applicationContext, note.id, note.title, note.subject)
    return Result.success()
}

आम गलतियाँ

  • GlobalScope.launch use करना → screen जाने के बाद भी काम चलता रहता है।
  • Coroutine में Thread.sleep → thread block; delay use करें।
  • CancellationException पकड़कर ignore करना → coroutine cancel नहीं हो पाती। इसे re-throw करें (या specific exceptions पकड़ें)।
  • Dispatchers.IO से view update → crash; Main पर लौटें (पहले withContext block खत्म करें)।

सारांश

  • suspend functions बिना block किए रुकते हैं; launch या async से शुरू करें।
  • UI के लिए Main, files/blocking I/O के लिए IO, CPU काम के लिए Default; withContext से बदलें।
  • viewModelScope और lifecycleScope use करें; risky calls try/catch में रखें।
✅ Practice

ViewModel में "profile" और "marks" (delay वाले दो suspend functions) async से parallel load कीजिए, loading के दौरान progress bar दिखाइए, और किसी के throw करने पर error Snackbar दिखाइए।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या Room और Retrofit को withContext(Dispatchers.IO) चाहिए?
नहीं। उनके suspend functions अंदर से ही background thread पर चले जाते हैं, इसलिए उन्हें main dispatcher वाले viewModelScope से call कर सकते हैं।
launch और async में क्या फ़र्क है?
launch ऐसा काम शुरू करता है जो result नहीं लौटाता (Job)। async Deferred लौटाता है जिसका result await() से मिलता है; parallel काम के लिए use करें।
क्या Android apps में runBlocking use होता है?
नहीं — यह thread block करता है। यह सिर्फ़ main() functions और tests के लिए है। Apps में viewModelScope या lifecycleScope use करें।
← Android Tutorial (Kotlin)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicRetrofit: REST API call करें आपकी प्रगति: 32 / 43 (74%) · Lesson 33 / 43 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें