launch — ουσία, εκκίνηση coroutine fire-and-forget και πώς λειτουργεί

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-06-22 Χρόνος ανάγνωσης: 7 λεπ

launch — Coroutine Builder στην Kotlin που εκκινεί μια coroutine χωρίς να επιστρέφει αποτέλεσμα, επιστρέφοντας ένα αντικείμενο Job για τη διαχείριση της εκτέλεσης. Αυτός ο builder υλοποιεί το μοτίβο fire-and-forget: η coroutine ξεκινά να εργάζεται σε ένα νήμα παρασκηνίου και τερματίζεται αυτόματα. Σύμφωνα με την τεκμηρίωση της JetBrains, 2024, το launch είναι ο κύριος τρόπος εκκίνησης παράλληλων εργασιών στο Kotlin Coroutines.

Κύρια σημεία

  • launch — builder για εκκίνηση coroutine χωρίς επιστροφή αποτελέσματος (fire-and-forget)
  • Job — αντικείμενο διαχείρισης coroutine με μεθόδους cancel(), join(), isActive
  • launch ενσωματώνεται με το CoroutineScope για αυτόματη ακύρωση θυγατρικών coroutine
  • CoroutineStart.LAZY επιτρέπει την καθυστέρηση εκκίνησης μέχρι ρητής κλήσης start() ή join()
  • launch στο Android χρησιμοποιείται για αποθήκευση σε ΒΔ, κλήσεις δικτύου και ενημέρωση UI

Τι είναι το launch στο Kotlin Coroutines;

launch — είναι μια συνάρτηση επέκτασης της Kotlin, διαθέσιμη μέσω του import kotlinx.coroutines, η οποία δημιουργεί μια νέα coroutine σε ένα καθορισμένο CoroutineScope. Σε αντίθεση με τις συνηθισμένες συναρτήσεις, ο κώδικας εντός του launch εκτελείται ταυτόχρονα — η coroutine μπορεί να ανασταλεί (suspend) χωρίς να μπλοκάρει το νήμα και να συνεχιστεί αργότερα.

Ο builder launch είναι ένα θεμελιώδες δομικό στοιχείο του μοντέλου coroutine της Kotlin. Δεν επιστρέφει μια υπολογισμένη τιμή, αλλά επιστρέφει ένα αντικείμενο Job που επιτρέπει τον έλεγχο της εκτέλεσης της coroutine. Όλες οι θυγατρικές coroutine που εκκινούνται μέσω launch εντός άλλης coroutine συνδέονται με τη γονική.

Σύνταξη και παράμετροι του launch

Ο builder launch ορίζεται ως inline συνάρτηση με πολλές παραμέτρους: CoroutineScope, CoroutineContext, CoroutineStart και suspend-block. Οι παράμετροι έχουν προεπιλεγμένες τιμές, καθιστώντας το launch βολικό για τυπικά σενάρια.

kotlin
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job

Η παράμετρος context δέχεται ένα CoroutineContext που συνδυάζει τον dispatcher, τον χειριστή εξαιρέσεων και ένα ονομασμένο στοιχείο. Συχνότερα μεταβιβάζονται Dispatchers.IO, Dispatchers.Main ή SupervisorJob για απομόνωση σφαλμάτων.

Job και διαχείριση κύκλου ζωής

Job — το επιστρεφόμενο αντικείμενο που αντιπροσωπεύει τον κύκλο ζωής της coroutine. Το Job μπορεί να βρίσκεται σε καταστάσεις: New, Active, Completing, Completed, Cancelling, Cancelled. Κάθε κατάσταση αντικατοπτρίζει την κατάσταση εκτέλεσης και επιτρέπει την αντίδραση σε αλλαγές.

kotlin
val job = CoroutineScope(Dispatchers.IO).launch {
    repeat(10) { i ->
        delay(1000L)
        println("Πρόοδος: $i")
    }
}

println("Το Job είναι ενεργό: ${job.isActive}")
delay(2500L)
job.cancel()
println("Το Job ακυρώθηκε: ${job.isCancelled}")

Το Job υποστηρίζει ιεραρχία: εάν η γονική coroutine ακυρωθεί, όλες οι θυγατρικές ακυρώνονται αυτόματα. Το SupervisorJob αλλάζει αυτήν τη συμπεριφορά — οι θυγατρικές coroutine δεν ακυρώνονται σε περίπτωση σφάλματος μιας από αυτές.

Δομημένη ταυτοχρονικότητα στο launch

Δομημένη ταυτοχρονικότητα σημαίνει ότι κάθε coroutine εκκινείται σε ένα συγκεκριμένο CoroutineScope και το scope δεν ολοκληρώνεται έως ότου όλες οι θυγατρικές coroutine ολοκληρώσουν την εργασία τους. Το launch υποστηρίζει πλήρως αυτήν την αρχή — οι coroutine που εκκινούνται εντός άλλης coroutine είναι θυγατρικές της.

Ένθετες κλήσεις launch

Κατά την ένθετη εκκίνηση launch σχηματίζεται ένα δέντρο coroutine. Η γονική coroutine αναμένει την ολοκλήρωση όλων των θυγατρικών, γεγονός που εγγυάται προβλέψιμη σειρά εκτέλεσης και απλοποιεί τη διαχείριση πόρων.

kotlin
fun main() = runBlocking {
    launch {
        launch {
            delay(1000L)
            println("Παιδί 1 ολοκληρώθηκε")
        }
        launch {
            delay(500L)
            println("Παιδί 2 ολοκληρώθηκε")
        }
        println("Όλα τα παιδιά ολοκληρώθηκαν πριν από αυτήν τη γραμμή")
    }
}

Αυτή η συμπεριφορά διαφέρει από την ταυτοχρονικότητα που βασίζεται σε νήματα, όπου τα θυγατρικά νήματα δεν συνδέονται με το γονικό. Στις coroutine, το γονικό δεν ολοκληρώνεται έως ότου όλα τα παιδιά ολοκληρώσουν την εργασία τους.

Διαχείριση εξαιρέσεων στο launch

Η διαχείριση εξαιρέσεων στο launch εξαρτάται από τον τύπο Job. Για ένα κανονικό Job, οι εξαιρέσεις διαδίδονται στη γονική coroutine και την ακυρώνουν. Για SupervisorJob ή SupervisorScope, οι εξαιρέσεις απομονώνονται — το σφάλμα μιας θυγατρικής coroutine δεν επηρεάζει τις άλλες.

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
    try {
        riskyOperation()
    } catch (e: Exception) {
        println("Συλλήφθηκε: ${e.message}")
    }
}
scope.launch {
    println("Αυτό ακόμα λειτουργεί χάρη στο SupervisorJob")
}

Για καθολική διαχείριση μη συλληφθέντων εξαιρέσεων χρησιμοποιείται το CoroutineExceptionHandler. Αυτό συλλαμβάνει εξαιρέσεις που δεν έχουν διαχειριστεί εντός της coroutine και επιτρέπει την καταγραφή του σφάλματος χωρίς κατάρρευση της εφαρμογής.

Παραδείγματα χρήσης του launch στο Android

Στο Android, το launch εφαρμόζεται παντού: από ViewModel έως WorkManager. Το κύριο μοτίβο είναι η χρήση lifecycleScope στο Fragment και viewModelScope στο ViewModel για αυτόματη ακύρωση coroutine κατά το τέλος του κύκλου ζωής του component.

kotlin
class ProfileViewModel : ViewModel() {
    private val repository = UserRepository()

    fun loadProfile(userId: String) {
        viewModelScope.launch(Dispatchers.IO) {
            val profile = repository.fetchProfile(userId)
            withContext(Dispatchers.Main) {
                _profileState.update { it.copy(profile = profile) }
            }
        }
    }
}

Το viewModelScope ακυρώνει αυτόματα τις coroutine κατά την καταστροφή του ViewModel. Αυτό εξαλείφει διαρροές μνήμης και εγγυάται ότι οι λειτουργίες παρασκηνίου δεν συνεχίζονται μετά την απώλεια περιβάλλοντος. Επιπλέον, μπορεί να χρησιμοποιηθεί withContext για εναλλαγή μεταξύ dispatcher.

Συχνές Ερωτήσεις

Σε τι διαφέρει το launch από το async στο Kotlin Coroutines;

launch επιστρέφει Job και δεν επιστρέφει αποτέλεσμα εκτέλεσης, ενώ το async επιστρέφει Deferred<T> για λήψη αποτελέσματος. Το launch χρησιμοποιείται για λειτουργίες fire-and-forget, το async — όταν πρέπει να περιμένετε και να χρησιμοποιήσετε την επιστρεφόμενη τιμή.

Πώς να ακυρώσετε μια coroutine που εκκινήθηκε μέσω launch;

Καλέστε job.cancel() στο αποθηκευμένο αντικείμενο Job. Για ομαδική ακύρωση, ακυρώστε ολόκληρο το CoroutineScope μέσω scope.cancel(). Η coroutine πρέπει να είναι συνεργατική — να ελέγχει το isActive ή να χρησιμοποιεί επαληθεύσιμες suspend συναρτήσεις.

Τι να κάνετε αν το launch έριξε εξαίρεση;

Χρησιμοποιήστε try-catch εντός του μπλοκ launch ή μεταβιβάστε CoroutineExceptionHandler στο CoroutineContext. Για απομόνωση σφαλμάτων χρησιμοποιήστε SupervisorJob — τότε η εξαίρεση σε μια θυγατρική coroutine δεν θα ακυρώσει τις υπόλοιπες.

Μπορεί το launch να ξεκινήσει χωρίς CoroutineScope;

Όχι, το launch είναι συνάρτηση επέκτασης του CoroutineScope. Χωρίς scope, η coroutine δεν μπορεί να ακολουθήσει την αρχή της δομημένης ταυτοχρονικότητας. Χρησιμοποιήστε το GlobalScope.launch με προσοχή — αυτό δημιουργεί μια coroutine χωρίς σύνδεση με τον κύκλο ζωής.

Πόσες launch coroutine μπορούν να ξεκινήσουν ταυτόχρονα;

Ο αριθμός περιορίζεται από τη δεξαμενή νημάτων του dispatcher. Dispatchers.Default χρησιμοποιεί αριθμό νημάτων ίσο με τον αριθμό πυρήνων CPU. Dispatchers.IO υποστηρίζει έως 64 νήματα. Κατά την εκκίνηση περισσότερων coroutine, αυτές μπαίνουν σε ουρά.

Σύνοψη

  • launch — κύριος builder για coroutine fire-and-forget, επιστρέφοντας αντικείμενο Job
  • Job παρέχει μεθόδους διαχείρισης: cancel(), join(), isActive, isCancelled, isCompleted
  • Δομημένη ταυτοχρονικότητα εγγυάται ακύρωση θυγατρικών coroutine κατά την ακύρωση της γονικής
  • Διαχείριση εξαιρέσεων εξαρτάται από τον τύπο Job: ο κανονικός διαδίδει σφάλματα, ο SupervisorJob απομονώνει
  • lifecycleScope και viewModelScope — έτοιμες λύσεις για εκκίνηση launch στο Android
  • CoroutineStart.LAZY καθυστερεί την εκκίνηση μέχρι ρητής κλήσης start() ή join()
  • Το launch στο Android εφαρμόζεται για αιτήματα δικτύου, εγγραφή σε ΒΔ, αναλυτικά στοιχεία και προσωρινή αποθήκευση

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης