Как да настроите и използвате корутини в Kotlin проекти?
sobes.tech AI
Отговор от AI
За настройка на корутините трябва да добавите съответната зависимост във файла 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() // Изчакване за завършване } - Отмяна: