Recomposition — τι είναι, ανακατασκευή UI κατά την αλλαγή κατάστασης

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

Recomposition είναι ένας μηχανισμός του Jetpack Compose που ανακατασκευάζει αυτόματα μέρη της διεπαφής χρήστη κατά την αλλαγή δεδομένων, χωρίς χειροκίνητη ενημέρωση των στοιχείων View. Όταν μια μεταβλητή κατάστασης από την οποία εξαρτάται μια Composable συνάρτηση αλλάζει τιμή, το Compose επανεκκινεί μόνο αυτήν τη συνάρτηση, αφήνοντας το υπόλοιπο δέντρο UI ανέπαφο. Σύμφωνα με τα δεδομένα Google Android Developers, 2026, η σωστή κατανόηση του Recomposition επιτρέπει τη μείωση του αριθμού των περιττών επανασχεδιάσεων κατά 40–60%.

Κύρια σημεία

  • Recomposition — επανεκκίνηση συναρτήσεων Composable κατά την αλλαγή των δεδομένων εισόδου ή της κατάστασης
  • Skipping — παράλειψη συναρτήσεων των οποίων οι παράμετροι δεν άλλαξαν (σύγκριση μέσω equals)
  • Stability καθορίζει αν το Compose μπορεί να παραλείψει μια συνάρτηση — οι σταθεροί τύποι συγκρίνονται σωστά
  • Smart Recomposition επανεκκινεί μόνο το ελάχιστο σύνολο συναρτήσεων, όχι ολόκληρο το δέντρο
  • Ανασύνθεση δεν εγγυάται επανασχεδίαση — Layout και Drawing μπορεί να παραλείψουν τη φάση

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

Recomposition είναι η εκ νέου εκτέλεση συναρτήσεων Composable που έχουν ήδη συμμετάσχει στο Composition, με νέες τιμές παραμέτρων ή κατάστασης. Ο κύριος σκοπός της ανασύνθεσης είναι ο συγχρονισμός του δέντρου UI με τα τρέχοντα δεδομένα χωρίς ανακατασκευή ολόκληρης της διεπαφής από την αρχή. Σε αντίθεση με το Composition που συμβαίνει εφάπαξ, το Recomposition μπορεί να εκκινηθεί εκατοντάδες φορές κατά τη διάρκεια ζωής μιας οθόνης.

Το Recomposition λειτουργεί με βάση την αρχή του smart invalidation: το Compose παρακολουθεί ποια αντικείμενα State διαβάζει κάθε Composable συνάρτηση και σημειώνει για επανεκκίνηση μόνο εκείνες των οποίων οι εξαρτήσεις άλλαξαν. Αυτό επιτυγχάνεται μέσω του συστήματος snapshot, το οποίο καταγράφει όλες τις λειτουργίες ανάγνωσης State κατά την εκτέλεση, και του Composer, ο οποίος αντιστοιχίζει αυτές τις εξαρτήσεις σε συγκεκριμένες συναρτήσεις.

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

Ενεργοποιητές ανασύνθεσης: τι προκαλεί επανεκκίνηση συναρτήσεων

Υπάρχουν τρεις κύριοι ενεργοποιητές ανασύνθεσης. Πρώτος — αλλαγή του αντικειμένου State που διαβάζεται στο σώμα της Composable συνάρτησης. Όταν το mutableStateOf ή derivedStateOf αλλάζει την τιμή του, όλες οι συναρτήσεις που κατέγραψαν την ανάγνωση αυτού του State στην προηγούμενη σύνθεση σημειώνονται για επανεκκίνηση.

Δεύτερος ενεργοποιητής — αλλαγή παραμέτρων της Composable συνάρτησης κατά την κλήση από τη γονική συνάρτηση. Εάν η γονική συνάρτηση μετέδωσε μια νέα τιμή (π.χ. άλλαξε το κείμενο ή ο αριθμός), η θυγατρική συνάρτηση θα επανεκκινηθεί, ακόμα κι αν δεν διαβάζει State εσωτερικά. Το Compose συγκρίνει τις νέες και παλιές τιμές παραμέτρων μέσω equals, και αν είναι ίσες — η συνάρτηση μπορεί να παραλειφθεί.

Τρίτος ενεργοποιητής — αλλαγή του CompositionLocal μέσω του CompositionLocalProvider. Όλες οι συναρτήσεις που διαβάζουν CompositionLocal μέσω .current επανεκκινούνται κατά την αλλαγή του provider. Αυτός ο μηχανισμός χρησιμοποιείται από το MaterialTheme: η αλλαγή θέματος (φωτεινό/σκοτεινό) προκαλεί ανασύνθεση όλων των στοιχείων που διαβάζουν το MaterialTheme.colorScheme.

kotlin
@Composable
fun RecompositionDemo() {
    var counter by remember { mutableStateOf(0) }
    var text by remember { mutableStateOf("Hello") }

    Column {
        Text("Μετρητής: $counter")  // ανασύνθεση όταν αλλάζει ο μετρητής
        Text("Μήνυμα: $text")    // ανασύνθεση όταν αλλάζει το κείμενο

        Button(onClick = { counter++ }) {
            Text("+1")
        }
        Button(onClick = { text = "Κόσμος" }) {
            Text("Αλλαγή κειμένου")
        }
    }
}

Το πάτημα του κουμπιού +1 αλλάζει το counter, που προκαλεί ανασύνθεση μόνο της πρώτης γραμμής Text και της ίδιας της Column. Η δεύτερη γραμμή Text, που εμφανίζει το text, δεν επανεκκινείται. Τέτοια απομόνωση — αποτέλεσμα του συστήματος snapshot: κάθε Composable συνάρτηση γνωρίζει μόνο για εκείνα τα αντικείμενα State που διάβασε.

Βελτιστοποίηση ανασύνθεσης: πρακτικές τεχνικές

Η βελτιστοποίηση της ανασύνθεσης ξεκινά με τη σωστή επιλογή δομών δεδομένων. Χρησιμοποιήστε αμετάβλητες συλλογές (listOf, mapOf) αντί για μεταβλητές (mutableListOf). Το Compose συγκρίνει τις παραμέτρους μέσω equals, και αν η συλλογή άλλαξε αλλά το equals επέστρεψε true — η συνάρτηση δεν θα επανεκκινηθεί. Για μεταβλητές συλλογές, χρησιμοποιήστε το SnapshotStateList, το οποίο υλοποιεί σωστή παρακολούθηση αλλαγών σε επίπεδο στοιχείων.

Δεύτερη τεχνική — εξαγωγή σταθερών τμημάτων UI σε ξεχωριστές Composable συναρτήσεις. Εάν ένα μέρος της οθόνης δεν εξαρτάται από συχνά μεταβαλλόμενη κατάσταση, εξάγετέ το σε ξεχωριστή συνάρτηση με παραμέτρους. Όταν έρχεται ανασύνθεση, η σταθερή συνάρτηση λαμβάνει τις ίδιες παραμέτρους, το Compose τις συγκρίνει και παραλείπει την εκτέλεση. Αυτό είναι πιο συμφέρον από το να επανεκκινείται αυτό το τμήμα στο πλαίσιο μιας μεγάλης συνάρτησης όπου μέρος των παραμέτρων άλλαξε.

Τρίτη τεχνική — κλειδιά στο LazyColumn. Πάντα να καθορίζετε key για το item στο LazyColumn, LazyGrid και άλλα τεμπέλικα κοντέινερ. Το κλειδί επιτρέπει στο Compose να αναγνωρίζει στοιχεία κατά την αλλαγή της λίστας: προσθήκη, διαγραφή ή αναδιάταξη. Χωρίς κλειδί, το Compose επανεκκινεί όλα τα στοιχεία της λίστας σε κάθε αλλαγή, που σε μεγάλες λίστες δίνει αισθητή απώλεια απόδοσης.

kotlin
// Βελτιστοποιημένη δομή: σταθερά μέρη εξαγμένα ξεχωριστά
@Composable
fun OptimizedScreen(items: List<Item>) {
    Column {
        Header()                         // δεν εξαρτάται από στοιχεία — καμία ανασύνθεση
        Spacer(modifier = Modifier.height(8.dp))
        LazyColumn {
            items(items, key = { it.id }) { item ->
                ItemRow(item = item)   // ανασύνθεση μόνο για αλλαγμένα στοιχεία
            }
        }
    }
}

@Composable
fun Header() {
    Text("Λίστα στοιχείων", style = MaterialTheme.typography.headlineMedium)
}

@Composable
fun ItemRow(item: Item) {
    Text(item.title)
}

Skipping και Stability στο Compose

Skipping είναι ένας μηχανισμός όπου το Compose παραλείπει την εκτέλεση μιας Composable συνάρτησης εάν όλες οι παράμετροί της δεν άλλαξαν. Για να λειτουργεί σωστά το skipping, οι τύποι παραμέτρων πρέπει να είναι σταθεροί (stable). Ο μεταγλωττιστής Kotlin σημειώνει ως σταθερούς: τους πρωτόγονους τύπους (Int, Float, Boolean), String, συναρτήσεις lambda, καθώς και κλάσεις των οποίων όλα τα πεδία είναι σταθερά και val.

Stability είναι ένας σχολιασμός @Stable ή @Immutable που μπορεί να προστεθεί σε προσαρμοσμένες κλάσεις δεδομένων. Εάν μια κλάση περιέχει μεταβλητό πεδίο (var), ο μεταγλωττιστής τη θεωρεί ασταθή και το Compose δεν μπορεί να παραλείψει συναρτήσεις με τέτοιες παραμέτρους. Για κλάσεις με var, χρησιμοποιήστε @Stable εάν εγγυάστε ότι η ειδοποίηση για αλλαγή θα σταλεί μέσω του συστήματος snapshot.

Το Stability μπορεί να ελεγχθεί μέσω σημαίας μεταγλωττιστή -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports". Αυτό δημιουργεί μια αναφορά με λίστα όλων των Composable συναρτήσεων και των παραμέτρων τους με ένδειξη stability. Εάν μια παράμετρος είναι ασταθής — το skipping για αυτήν τη συνάρτηση είναι αδύνατο και θα επανεκκινείται σε κάθε ανασύνθεση του γονέα.

ΤύποςΣταθερότηταSkipping
Int, Float, BooleanΣταθερόςΝαι
StringΣταθερόςΝαι
LambdaΣταθερόςΝαι
data class με πεδία valΣταθερόςΝαι
data class με πεδία varΑσταθήςΌχι
List<String>ΑσταθήςΌχι

Σημειώστε: η List<String> θεωρείται ασταθής επειδή είναι διεπαφή, όχι συγκεκριμένη υλοποίηση. Χρησιμοποιήστε το immutableListOf() από τη βιβλιοθήκη Kotlin Collections Immutable ή τυλίξτε τη λίστα σε μια @Stable κλάση. Η Lambda είναι πάντα σταθερή, επειδή το equals της συγκρίνει μόνο αναφορές, και κατά τη δημιουργία μιας νέας lambda στο σημείο κλήσης, η γονική συνάρτηση επίσης επανεκκινείται.

Παρακολούθηση ανασυνθέσεων στο Android Studio

Για την παρακολούθηση ανασυνθέσεων, το Android Studio παρέχει το Layout Inspector με λειτουργία Compose Recomposition Counts. Σε αυτήν τη λειτουργία, κάθε Composable συνάρτηση εμφανίζει τον αριθμό ανασυνθέσεων και τους λόγους επανεκκίνησης. Αυτό επιτρέπει τον γρήγορο εντοπισμό συναρτήσεων που ανασυντίθενται πολύ συχνά και τον προσδιορισμό της βασικής αιτίας — ασταθείς παράμετροι ή περιττές εξαρτήσεις State.

Πρόσθετα εργαλεία: Compose Metrics (συλλογή στατιστικών μέσω δοκιμών instrumentation) και Recomposition Timer (μέτρηση χρόνου εκτέλεσης κάθε συνάρτησης). Η Google συνιστά την ενεργοποίηση αυτών των εργαλείων στο στάδιο προφίλ και την απενεργοποίηση στις εκδόσεις release, καθώς προσθέτουν επιβάρυνση έως 20% σε κάθε ανασύνθεση.

Κατά την ανάλυση ανασυνθέσεων, αναζητήστε μοτίβα unnecessary recomposition: μια συνάρτηση επανεκκινείται παρόλο που το UI εξόδου της δεν θα πρέπει να αλλάξει. Συχνή αιτία είναι η χρήση lambda χωρίς remember, όταν κάθε φορά δημιουργείται ένα νέο αντικείμενο lambda και το Compose θεωρεί την παράμετρο αλλαγμένη. Λύση: τύλιγμα των lambda σε remember { } με σταθερές λήψεις.

kotlin
// Κακό: νέα lambda σε κάθε ανασύνθεση γονέα
@Composable
fun Parent() {
    Child(onClick = { doSomething() })  // νέα lambda κάθε φορά
}

// Καλό: το remember σταθεροποιεί τη lambda
@Composable
fun Parent() {
    val onClick = remember { { doSomething() } }
    Child(onClick = onClick)  // ίδια αναφορά
}

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

Σημαίνει η ανασύνθεση επανασχεδίαση της οθόνης;

Όχι, η ανασύνθεση είναι μόνο η φάση Composition. Μετά από αυτήν εκτελούνται Layout και Drawing. Εάν μετά την ανασύνθεση τα μεγέθη και οι θέσεις των στοιχείων δεν άλλαξαν, τα Layout και Drawing μπορούν να παραλειφθούν πλήρως, εξοικονομώντας πόρους GPU.

Πόσο συχνά μπορεί να συμβεί ανασύνθεση;

Σε κινούμενα σχέδια, η ανασύνθεση μπορεί να εκκινηθεί έως και 120 φορές το δευτερόλεπτο (120fps). Για κανονική αλληλεπίδραση — 10–60 φορές το δευτερόλεπτο. Είναι σημαντικό κάθε ανασύνθεση να χωράει στον προϋπολογισμό καρέ (8–16 ms), διαφορετικά η εφαρμογή θα καθυστερεί.

Γιατί μια συνάρτηση ανασυντίθεται ενώ το State δεν άλλαξε;

Αιτία — αλλαγή παραμέτρου από τη γονική συνάρτηση. Ο γονέας επανεκκινείται (για δικό του λόγο) και μεταδίδει μια νέα τιμή. Για να το αποφύγετε, ελέγξτε το stability των παραμέτρων και χρησιμοποιήστε remember για σταθεροποίηση lambda και υπολογισμένων τιμών.

Μπορεί να απενεργοποιηθεί η ανασύνθεση για μια συγκεκριμένη συνάρτηση;

Δεν υπάρχει άμεση απενεργοποίηση, αλλά υπάρχει αναγκαστική παράλειψη μέσω readInComposition — το State διαβάζεται εκτός του σώματος της συνάρτησης, το οποίο δεν καταγράφει εξάρτηση. Χρησιμοποιήστε το με προσοχή: η συνάρτηση δεν θα αντιδρά σε αλλαγές, που μπορεί να οδηγήσει σε παρωχημένο UI.

Τι είναι πιο ακριβό: Composition ή Recomposition;

Το Composition είναι πιο ακριβό επειδή δημιουργεί όλες τις υποδοχές και τους κόμβους του δέντρου από την αρχή. Το Recomposition επαναχρησιμοποιεί υπάρχουσες υποδοχές και ενημερώνει μόνο τις τιμές τους. Στην πράξη, το Composition μιας οθόνης διαρκεί 2–10 ms και η ανασύνθεση ενός στοιχείου — 0.1–1 ms.

Σύνοψη

  • Recomposition — επιλεκτική επανεκκίνηση συναρτήσεων Composable κατά την αλλαγή State ή παραμέτρων τους
  • Snapshot system παρακολουθεί τις εξαρτήσεις συναρτήσεων από State και προγραμματίζει ανασύνθεση
  • Skipping είναι δυνατό μόνο για συναρτήσεις με σταθερές παραμέτρους (@Stable ή immutable)
  • Τρεις ενεργοποιητές ανασύνθεσης: αλλαγή State, αλλαγή παραμέτρων, αλλαγή CompositionLocal
  • List<T> θεωρείται ασταθής — χρησιμοποιήστε αμετάβλητες συλλογές για σωστό skipping
  • Layout Inspector δείχνει μετρητές ανασύνθεσης για κάθε συνάρτηση
  • Σύσταση: εξάγετε σταθερά μέρη UI σε ξεχωριστές συναρτήσεις και χρησιμοποιήστε remember για lambda

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

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

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

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