Composition: ουσία, δημιουργία δέντρου UI στο Compose

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

Composition — είναι η κεντρική διαδικασία στο Jetpack Compose, κατά την οποία από περιγραφικές Composable συναρτήσεις χτίζεται ένα ζωντανό δέντρο UI που εμφανίζεται στην οθόνη. Σε αντίθεση με το σύστημα View στο Android, όπου η διάταξη φορτωνόταν από XML και μετατρεπόταν σε αμετάβλητα αντικείμενα, το Composition λειτουργεί ως δυναμικό σύστημα: οι συναρτήσεις εκτελούνται, δημιουργούν slots στη μνήμη, σχηματίζουν ιεραρχία κόμβων και τη συνδέουν με την κατάσταση. Σύμφωνα με το Google Android Developers, 2026, η κατανόηση του Composition είναι κρίσιμη για τη βελτιστοποίηση της απόδοσης εφαρμογών Compose.

Κύρια σημεία

  • Composition — εκτέλεση Composable συναρτήσεων για τη δημιουργία δέντρου UI
  • Slots — κελιά μνήμης που αποθηκεύουν παραμέτρους και κατάσταση κάθε συνάρτησης
  • Θέση στο Compose (Positional Memorization) συνδέει την κατάσταση με τη θέση στον κώδικα
  • Πρώτο πέρασμα Composition δημιουργεί το αρχικό δέντρο UI κατά την εκκίνηση της οθόνης
  • CompositionLocal μεταφέρει δεδομένα μέσω του δέντρου χωρίς ρητές παραμέτρους

Τι είναι το Composition στο Jetpack Compose

Composition — είναι η διαδικασία εκτέλεσης Composable συναρτήσεων, με αποτέλεσμα τη δημιουργία εσωτερικής αναπαράστασης της διεπαφής χρήστη με τη μορφή δέντρου κόμβων. Κάθε κόμβος αυτού του δέντρου αντιστοιχεί είτε σε ενσωματωμένο στοιχείο (Text, Button, Image) είτε σε κλήση προσαρμοσμένης Composable συνάρτησης. Το Composition δεν δημιουργεί άμεσα αντικείμενα View Android — χτίζει μια αφηρημένη περιγραφή που στη συνέχεια επεξεργάζονται οι φάσεις Layout και Drawing.

Το βασικό χαρακτηριστικό του Composition είναι η δυνατότητα επανεκκίνησης (restartability). Κάθε Composable συνάρτηση στη σύνθεση μπορεί να επανεκκινηθεί οποιαδήποτε στιγμή, αν αλλάξουν οι παράμετροι εισόδου της ή τα αντικείμενα κατάστασης που διάβασε. Το σύστημα δεν επανεκκινεί ολόκληρο το δέντρο — μόνο εκείνες τις συναρτήσεις που εξαρτώνται πραγματικά από τα αλλαγμένα δεδομένα.

Τεχνικά, το Composition διαχειρίζεται μέσω του Composer — μιας εσωτερικής μηχανής που ο μεταγλωττιστής Kotlin ενσωματώνει σε κάθε Composable συνάρτηση. Ο Composer γράφει σε slots (ομάδες θέσεων) πληροφορίες για το ποιες συναρτήσεις κλήθηκαν, με ποιες παραμέτρους και με ποια σειρά. Σε επόμενες κλήσεις, ο Composer συγκρίνει τα νέα δεδομένα με τα αποθηκευμένα και αποφασίζει για επανεκκίνηση.

Πώς χτίζεται το δέντρο UI στη διαδικασία Composition

Η διαδικασία δημιουργίας του δέντρου UI ξεκινά με την κλήση της μεθόδου setContent μέσα στο Activity ή Fragment. Αυτή η μέθοδος δημιουργεί το αρχικό Composition και εκκινεί την εκτέλεση της ριζικής Composable συνάρτησης. Στη συνέχεια, κάθε ένθετη Composable συνάρτηση προσθέτει τους κόμβους της στο δέντρο, σχηματίζοντας ιεραρχία: Row περιέχει Text και Button, Column περιέχει Image και Card, και ούτω καθεξής.

Κάθε κόμβος του δέντρου λαμβάνει ένα μοναδικό κλειδί θέσης, βασισμένο στη θέση του στον πηγαίο κώδικα. Αυτό το κλειδί χρησιμοποιείται για την ταυτοποίηση του κόμβου σε επαναλαμβανόμενες εκτελέσεις. Το κλειδί θέσης είναι ο λόγος για τον οποίο η σειρά κλήσης των Composable συναρτήσεων δεν πρέπει να εξαρτάται από συνθήκες: αν σε μια εκτέλεση κλήθηκαν A -> B, και στην επόμενη B -> A, το Compose δεν θα μπορέσει να αντιστοιχίσει τους παλιούς και νέους κόμβους.

kotlin
@Composable
fun AppScreen() {
    Column {                     // Κόμβος Column (θέση 1)
        HeaderSection()            // Κόμβος HeaderSection (θέση 2)
        ContentSection()           // Κόμβος ContentSection (θέση 3)
        FooterSection()            // Κόμβος FooterSection (θέση 4)
    }
}

@Composable
fun HeaderSection() {
    Row {                       // Κόμβος Row (θέση 2.1)
        Text("Τίτλος")         // Κόμβος Text (θέση 2.2)
        Icon(...)                // Κόμβος Icon (θέση 2.3)
    }
}

Σε αυτό το παράδειγμα, κάθε κλήση λαμβάνει μια θέση βασισμένη στη σειρά στον κώδικα. Column (θέση 1) περιέχει τρεις θυγατρικούς κόμβους (θέσεις 2, 3, 4). HeaderSection προσθέτει άλλους δύο θυγατρικούς κόμβους (2.1, 2.2, 2.3). Αν στην επόμενη ανασύνθεση το ContentSection κληθεί πριν από το HeaderSection, ο Composer δεν θα μπορέσει να αντιστοιχίσει σωστά τους κόμβους — εξ ου και ο κανόνας: η σειρά κλήσης των Composable συναρτήσεων πρέπει να είναι σταθερή.

Διαχείριση κατάστασης στο Composition

Η κατάσταση στο Composition διαχειρίζεται μέσω αντικειμένων τύπου State<T>. Όταν μια Composable συνάρτηση διαβάζει μια τιμή από State μέσω μιας εκχωρημένης ιδιότητας (by), καταγράφει μια εξάρτηση από αυτό το State. Όταν η τιμή αλλάξει, όλες οι συναρτήσεις που διάβασαν αυτό το State σημειώνονται για επανεκκίνηση στην επόμενη φάση της σύνθεσης.

Ο μηχανισμός καταγραφής εξαρτήσεων ονομάζεται σύστημα snapshot. Κάθε φορά που το State αλλάζει, το snapshot καταγράφει όλες τις αλλαγές και ειδοποιεί τον Composer ποιες συναρτήσεις εξαρτώνται από αυτό το State. Είναι σημαντικό να κατανοηθεί: η ανάγνωση State σε μη Composable κώδικα (π.χ. σε lambda onClick) δεν καταγράφει εξάρτηση — μόνο η ανάγνωση μέσα σε Composable συνάρτηση ή σε lambda που εκτελούνται στο πλαίσιο της σύνθεσης.

Το σύστημα snapshot λειτουργεί συναλλαγματικά: πολλές αλλαγές State στο πλαίσιο ενός γεγονότος συνδυάζονται σε μία συναλλαγή, αποτρέποντας πολλαπλές ανασυνθέσεις. Αυτό είναι ιδιαίτερα σημαντικό στην επεξεργασία χειρονομιών: κατά τη διάρκεια μιας κίνησης αλλάζουν πολλά αντικείμενα State, αλλά το Compose εκτελεί μόνο μία ανασύνθεση.

kotlin
@Composable
fun StateExample() {
    var text by remember { mutableStateOf("Hello") }
    var isVisible by remember { mutableStateOf(true) }

    Column {
        Text(text)  // καταγράφει εξάρτηση από το text

        if (isVisible) {  // καταγράφει εξάρτηση από το isVisible
            TextField(value = text, onValueChange = { text = it })
        }

        Button(onClick = { isVisible = !isVisible }) {
            Text(if (isVisible) "Απόκρυψη" else "Εμφάνιση")
        }
    }
}

Η αλλαγή του text οδηγεί σε ανασύνθεση μόνο των Column, Text και TextField. Το Button και η συνθήκη isVisible παραμένουν αμετάβλητα. Αυτή η απομόνωση της ανασύνθεσης είναι ένα βασικό πλεονέκτημα του Compose έναντι συστημάτων που επανασχεδιάζουν ολόκληρη την οθόνη. Κάθε Composable συνάρτηση παρακολουθεί μόνο εκείνα τα αντικείμενα State που διαβάζει άμεσα.

Composition vs Recomposition: βασικές διαφορές

Composition (σύνθεση) και Recomposition (ανασύνθεση) — είναι δύο διαφορετικοί τρόποι εκτέλεσης Composable συναρτήσεων. Το Composition συμβαίνει μία φορά κατά τη δημιουργία της οθόνης: το σύστημα εκτελεί όλες τις Composable συναρτήσεις με αρχικές τιμές και χτίζει το αρχικό δέντρο UI. Η Recomposition συμβαίνει πολλές φορές κατά την αλλαγή δεδομένων: το σύστημα επανεκκινεί μόνο εκείνες τις συναρτήσεις που εξαρτώνται από την αλλαγμένη κατάσταση.

Η λειτουργία Composition ενεργοποιεί όλους τους κόμβους του δέντρου, εκχωρεί slots για κάθε συνάρτηση, καταγράφει όλους τους απογόνους. Η Recomposition λειτουργεί επιλεκτικά: ο Compose συγκρίνει νέες και παλιές τιμές παραμέτρων κάθε συνάρτησης, και αν δεν έχουν αλλάξει — η συνάρτηση δεν εκτελείται (skipping).

Το Composition και η Recomposition διαφέρουν σε κόστος. Το πρώτο Composition είναι πιο ακριβό, καθώς απαιτεί πλήρη δημιουργία του δέντρου και εκχώρηση slots. Η Recomposition είναι φθηνότερη, ειδικά αν οι περισσότερες συναρτήσεις είναι σταθερές — οι παράμετροί τους συγκρίνονται με equals, και ο Compose παραλείπει την κλήση τους. Για μέγιστη απόδοση, πρέπει να επιδιώκεται όσο το δυνατόν λιγότερες συναρτήσεις να επηρεάζονται από ανασύνθεση.

ΧαρακτηριστικόCompositionRecomposition
Πότε συμβαίνειΜία φορά, στην πρώτη εμφάνισηΠολλές φορές, κατά αλλαγή δεδομένων
ΈκτασηΟλόκληρο το δέντροΜόνο αλλαγμένες συναρτήσεις
Σύγκριση παραμέτρωνΔεν εκτελείταιΕκτελείται για skipping
Δημιουργία slotsΝαι, όλα τα slots δημιουργούνταιΜόνο για νέους κόμβους

CompositionLocal: μεταφορά δεδομένων μέσω δέντρου

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

Το θέμα MaterialTheme — το πιο γνωστό παράδειγμα CompositionLocal. Όλα τα στοιχείο του Compose διαβάζουν χρώματα, τυπογραφία και σχήματα μέσω MaterialTheme.colorScheme, MaterialTheme.typography, MaterialTheme.shapes, χωρίς να τα λαμβάνουν μέσω παραμέτρων. Ο προγραμματιστής μπορεί να δημιουργήσει δικά του CompositionLocal για δεδομένα όπως ο τρέχων χρήστης, ρυθμίσεις τοπικής προσαρμογής ή διαμόρφωση οθόνης.

Σημαντικός περιορισμός: το CompositionLocal δεν πρέπει να χρησιμοποιείται για δεδομένα που αλλάζουν συχνά (θέση κύλισης, κείμενο σε πεδίο εισόδου). Το στοιχείο που διαβάζει CompositionLocal επανεκκινείται σε κάθε αλλαγή τιμής, επομένως για δυναμικά δεδομένα είναι καλύτερο να χρησιμοποιούνται ρητές παράμετροι ή State. Το CompositionLocal είναι βέλτιστο για δεδομένα διαμόρφωσης που αλλάζουν σπάνια ή ποτέ.

kotlin
val LocalUser = compositionLocalOf<User?> { null }

@Composable
fun AppRoot(user: User, content: @Composable () -> Unit) {
    CompositionLocalProvider(LocalUser.provides(user)) {
        content()
    }
}

@Composable
fun UserAvatar() {
    val user = LocalUser.current  // ανάγνωση χωρίς ρητή παράμετρο
    AsyncImage(model = user?.avatarUrl, contentDescription = "Avatar")
}

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

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

Τι συμβαίνει αν το State αλλάξει κατά τη διάρκεια του Composition;

Η αλλαγή του State κατά τη διάρκεια του Composition προγραμματίζει μια νέα ανασύνθεση που θα εκτελεστεί μετά την ολοκλήρωση της τρέχουσας. Δεν δημιουργείται βρόχος: το Compose εγγυάται ότι κάθε ανασύνθεση εκτελείται σε ξεχωριστή συναλλαγή του συστήματος snapshot.

Πόσο χρόνο διαρκεί το Composition μιας σύνθετης οθόνης;

Σε σύγχρονες συσκευές, το Composition μιας οθόνης με 50–100 Composable συναρτήσεις διαρκεί 1–5 ms. Η Google συνιστά να παραμένει εντός 16 ms ανά καρέ στα 60fps. Αν το Composition υπερβαίνει αυτό το όριο, χρησιμοποιήστε LazyColumn ή χωρίστε την οθόνη σε μικρότερες συναρτήσεις.

Μπορεί να εκκινηθεί το Composition χειροκίνητα;

Η άμεση χειροκίνητη εκκίνηση του Composition δεν είναι δυνατή — διαχειρίζεται αυτόματα από τον Composer. Ωστόσο, μπορεί να εξαναγκαστεί ο προγραμματισμός ανασύνθεσης αλλάζοντας το State ή καλώντας invalidate() στο ριζικό composite, αν υπάρχει πρόσβαση στο CompositionContext.

Σε τι διαφέρει το Composition από την ιεραρχία View στο κλασικό Android;

Η ιεραρχία View — είναι ένα αμετάβλητο δέντρο αντικειμένων Java που δημιουργείται μία φορά. Composition — ένα εικονικό δέντρο που αναδομείται σε κάθε αλλαγή δεδομένων. Το View αποθηκεύει την κατάστασή του σε μεταβλητές στιγμιοτύπου, το Composition — σε slots συνδεδεμένα με τη θέση κλήσης της συνάρτησης.

Πώς διαχειρίζεται το Composition τη διαγραφή κόμβων;

Αν μια Composable συνάρτηση πάψει να καλείται (π.χ. η συνθήκη if γίνει false), το Composition διαγράφει τον κόμβο της και καλεί την εκκαθάριση του DisposableEffect. Κατά την επανεμφάνιση (if γίνει ξανά true) δημιουργείται νέος κόμβος — ο παλιός δεν αποκαθίσταται.

Σύνοψη

  • Composition — διαδικασία εκτέλεσης Composable συναρτήσεων για τη δημιουργία δέντρου UI συνδεδεμένου με κατάσταση
  • Composer διαχειρίζεται slots, καταγράφει κλήσεις συναρτήσεων και συγκρίνει παραμέτρους κατά την ανασύνθεση
  • Σύστημα snapshot καταγράφει εξαρτήσεις συναρτήσεων από State και συνδυάζει αλλαγές σε συναλλαγές
  • Composition εκτελείται μία φορά κατά την εκκίνηση, Recomposition — κατά αλλαγή δεδομένων
  • CompositionLocal μεταφέρει δεδομένα διαμόρφωσης μέσω δέντρου χωρίς ρητή αλυσίδα παραμέτρων
  • Θέση κλήσης συνάρτησης χρησιμεύει ως μοναδικό αναγνωριστικό της στο δέντρο σύνθεσης
  • Σύσταση: δημιουργείτε μικρές Composable συναρτήσεις με αμετάβλητες παραμέτρους για αποτελεσματικό skipping

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

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

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

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