{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreigfv3jwggww5qofuiwsjqgzof277i4ipltenqikegwfp3j6x2adma",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mowvpy5odyy2"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreicv3wdjmmf7q6y7xq4dfjt3yxjlyzqjmo4neuc33isx6ayckhxlmm"
},
"mimeType": "image/webp",
"size": 60384
},
"path": "/manoj_saichallagulla_798/viewmodel-vs-coroutine-scope-oln",
"publishedAt": "2026-06-23T07:05:01.000Z",
"site": "https://dev.to",
"tags": [
"android",
"beginners",
"mobile",
"tutorial"
],
"textContent": "## 1. Coroutine\n\nA coroutine is the actual background task.\n\nExample:\n\n\n\n launch {\n api.getProfile()\n }\n\n\nHere, the work is:\n\n## api.getProfile()\n\nSo coroutine means:\n\nA lightweight task that can run without blocking the main thread.\n\n## 2. CoroutineScope\n\nA CoroutineScope is like a container/manager for coroutines.\n\nIt decides:\n\n\n\n Where coroutine runs\n How long coroutine lives\n When coroutine should be cancelled\n\n\nExample:\n\n\n\n val scope = CoroutineScope(Dispatchers.IO)\n\n scope.launch {\n // coroutine work\n }\n\n\nHere:\n\n\n\n scope = manager\n launch block = coroutine\n\n\n\n## 3. viewModelScope\n\nviewModelScope is a special CoroutineScope given by Android to every ViewModel.\n\nExample:\n\n\n\n class ProfileViewModel : ViewModel() {\n\n fun loadProfile() {\n viewModelScope.launch {\n repository.getProfile()\n }\n }\n }\n\n\nMeaning:\n\nRun this coroutine inside the ViewModel’s scope.\n\n\n\n 4. Relationship\n\n\nVery important:\n\n\n\n CoroutineScope is the general concept.\n\n viewModelScope is one specific CoroutineScope.\n\n Coroutine is the actual task running inside the scope.\n\n\nLike this:\n\n\n\n ViewModel\n owns\n viewModelScope\n manages\n coroutines\n\n\nVisual:\n\n`ProfileViewModel\n│\n└── viewModelScope\n│\n├── coroutine 1 → API call\n├── coroutine 2 → DB operation\n└── coroutine 3 → file operation`\n\n## 5. Why use viewModelScope?\n\nBecause it automatically cancels coroutines when ViewModel is cleared.\n\n\n\n viewModelScope.launch {\n delay(10000)\n println(\"Done\")\n }\n\n\nIf user leaves the screen before 10 seconds:\n\n\n\n Screen closed\n ↓\n ViewModel cleared\n ↓\n viewModelScope cancelled\n ↓\n Coroutine cancelled\n\n\nSo \"Done\" will not print.\n\n## 6. Without viewModelScope\n\n\n val scope = CoroutineScope(Dispatchers.IO)\n\n scope.launch {\n delay(10000)\n println(\"Done\")\n }\n\n\nHere you created the scope manually.\n\nSo you must cancel it manually:\n\n\n\n scope.cancel()\n\n\n\nOtherwise it may continue even after the screen is gone.\n\n## 7. Final Note\n\n\n Write this in your notes:\n\n Coroutine = actual background task.\n\n CoroutineScope = manager/container that controls coroutines.\n\n viewModelScope = Android-provided CoroutineScope attached to ViewModel.\n\n When ViewModel is cleared, viewModelScope is automatically cancelled.\n\n So all coroutines launched inside viewModelScope are also cancelled.\n\n\n\nBest simple line:\n\nviewModelScope.launch { } means:\n\n\n\n Run this coroutine as long as the ViewModel is alive.\n",
"title": "ViewModel VS Coroutine Scope"
}