Middle
Kako konfigurisati i koristiti korutine u Kotlin projektima?
sobes.tech АИ
Одговор од АИ
За подешавање кортина потребно је додати одговараву зависност у датотеку build.gradle.
// build.gradle (модул апликације)
dependencies {
//... друге зависности
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // за JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // за Android (ако је потребан Dispatchers.Main)
}
Користење кортина укључује:
-
Област живота (Scope): Одређује област у којој ће корутине бити извршаване и управљати својим животним циклусом.
GlobalScope: Област живота целе апликације, користити опрезно, јер може доћи до цурења меморије.CoroutineScope: Јасно креирано, омогућава контролу отказивања кортина.- Предодређене области у оквирима (нпр.
lifecycleScopeу Android ViewModel-у).
// Пример са CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Креирање Scope-а са Dispatcher-ом и Job-ом fun performBackgroundTask() { myScope.launch { // Покретање корутине // Дугачки процес израчунавања } } fun cancelAllTasks() { myScope.cancel() // Отказивање свих кортина у Scope-у } -
Креираоци кортина (Builders): Функције за покретање кортина.
launch: Покреће корутину која не враћа резултат експлицитно (Job).async: Покреће корутину која враћа резултат у обликуDeferred.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - builder за структурирану конкуренцију val data1 = async { networkCall1() } // async враћа Deferred val data2 = async { networkCall2() } // ... обрада података након добијања data1.await() // Добијање резултата из Deferred, корутина се спава до завршетка data2.await() } suspend fun networkCall1(): String { delay(1000) // Имитација мрежног захтева return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - builder за блокирање тренутног тока (нпр. main или тестови) launch { // launch враћа Job println("Fetching data...") fetchData() println("Data fetched!") } } -
Диспетчери (Dispatchers): Одређују на којем току или пулу токова ће се извршавати корутина.
Dispatchers.Default: За CPU-интензивне задатке.Dispatchers.IO: За блокирајуће I/O операције (датотеке, мрежа).Dispatchers.Main: Главни ток (само за Android и Swing/JavaFX).Dispatchers.Unconfined: Покреће корутину у позивајућем току, спава се и наставља у току који је обновио извршавање.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Навођење диспетчера // Извршавање I/O операције println("Running on thread: ${Thread.currentThread().name}") } } fun main() = runBlocking { launch(Dispatchers.Default) { println("Default thread: ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { println("Unconfined thread 1: ${Thread.currentThread().name}") delay(100) // Спавање println("Unconfined thread 2: ${Thread.currentThread().name}") // Обнова у другом току (можда) } delay(200) // Чекање на завршетак кортина } -
Функције за заустављање (Suspending functions): Функције означене кључном речи
suspend, које могу бити заустављене и настављене без блокирања тока. Могу се позивати само из других заустављивих функција или из блока корутине. -
Обрада отказивања и изузетака: Корутине подржавају структурирано отказивање и ширење изузетака.
- Отказивање:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Working $i ...") delay(100) // спирајућа функција која поштује отказивање } } catch (e: CancellationException) { println("Task was cancelled!") } finally { println("Cleaning up...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Чекање job.cancelAndJoin() // Отказивање и чекање на завршетак } - Изузеци: У случају
launch, неухваћено изузеће ће довести до пада апликације (по подразумевану у Android). У случајуasync, изузеће ће бити изведено при позивуawait(). За финију контролу користе сеCoroutineExceptionHandlerилиSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Caught exception: $exception") } val job = GlobalScope.launch(handler) { // Примена обработљача изузетака throw IllegalStateException("Something went wrong") } job.join() // Чекање на завршетак } - Отказивање: