Как создать свой ViewModelScope

Ответ

Для создания ViewModelScope в Android используйте viewModelScope, который автоматически предоставляется классом ViewModel. Он привязан к жизненному циклу ViewModel и отменяется при ее очистке (onCleared).

Пример:

class MyViewModel : ViewModel() {  
    fun fetchData() {  
        viewModelScope.launch {  
            // Код корутины (например, вызов suspend-функций)  
        }  
    }  
}  

Если нужно создать кастомный CoroutineScope (например, для тестов), можно использовать:

private val customScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)  

override fun onCleared() {  
    customScope.cancel()  
    super.onCleared()  
}  

Важно: Для работы viewModelScope добавьте зависимость:

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"  

Ответ 18+ 🔞

Э, слушай, тут народ постоянно спрашивает, как с корутинами в ViewModel не облажаться. Ну, блядь, всё просто, как три копейки!

Вот смотри, чтобы не выдумывать велосипед, в Android уже всё придумали за нас, ленивых жоп. Есть такая штука — viewModelScope. Это типа твой личный раб-корутинщик, который прибит гвоздями к жизненному циклу самой ViewModel. Создал ViewModel — scope уже есть. ViewModel почистили (вызвали onCleared) — все корутины в этом scope автоматом, по-тихому, накрылись медным тазом. Красота, ёпта!

Вот как это выглядит в коде, смотри не запоролись:

class MyViewModel : ViewModel() {  
    fun fetchData() {  
        viewModelScope.launch {  
            // Тут твой код, который что-то там тянет с сервака или из базы
            // Главное — suspend функции вызывай, не парься
        }  
    }  
}  

Всё! Запустил fetchData() — корутина поехала. Пользователь экран закрыл, ViewModel умерла — корутина тупо отменилась. Никаких утечек памяти, всё чисто. Удивление пиздец, как же просто!

А что, если ты такой хитрожопый и хочешь свой собственный scope, ну, например, для тестов, чтобы мокать диспетчеры? Ну, валидный запрос, бывает. Тогда делаешь так:

private val customScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)  

override fun onCleared() {  
    customScope.cancel() // Не забудь ручками прибить, а то будет висеть, как сопля!
    super.onCleared()  
}

Но, блядь, честно? В 99% случаев viewModelScope хватает за глаза и за уши. Зачем городить огород?

О, и самое главное, чувак! Чтобы эта магия viewModelScope вообще работала, не забудь в build.gradle добавить строчку, а то будешь потом чесать репу, почему компилятор матерится.

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"  

Вот и вся наука. Никакой ебалы с ручным управлением Job'ами, никакого страха, что корутина переживёт фрагмент. Всё аккуратно и по-взрослому. Пизда рулю, как говорится.