Middle
როგორ დავაყენოთ და გამოვიყენოთ კორუტინები 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: აშკარად შექმნილი, საშუალებას აძლევს გაუქმება.- ფრემვორკების წინასწარ განსაზღვრული სივრცეები (მაგალითად,
lifecycleScopeAndroid ViewModel-ში).
// მაგალითი CoroutineScope-ით val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // შექმნა Scope-ით Dispatcher და Job fun performBackgroundTask() { myScope.launch { // კორუტინის დაწყება // ხანგრძლივი გამოთვლითი პროცესი } } fun cancelAllTasks() { myScope.cancel() // ყველა კორუტინის გაუქმება } -
კორუტინების შემქმნელები (Builders): ფუნქციები კორუტინების დასაწყებად:
launch: იწყებს კორუტინს, რომელიც არ აბრუნებს შედეგს (აბრუნებსJob-ს).async: იწყებს კორუტინს, რომელიც აბრუნებს შედეგსDeferred-ის სახით:
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - სტრუქტურირებული კონკურენტობის ბილდერი 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 - ბლოკავს მიმდინარე ნაკადს 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() // დასრულების მოლოდინი } - გაუქმება: