RenderObject Tree — is het derde niveau van de hiërarchie in Flutter, verantwoordelijk voor de daadwerkelijke weergave van de interface op het scherm. Elk knooppunt van deze boom voert de berekening van afmetingen (layout) en tekenen (painting) uit, waarbij de configuratie van widgets wordt omgezet in pixels. In tegenstelling tot Widget Tree wordt RenderObject Tree eenmalig aangemaakt en alleen bijgewerkt bij wijziging van geometrie of uiterlijk. Volgens Flutter API Reference, 2025 bepaalt de efficiëntie van RenderObject Tree direct de vloeiendheid van animaties en de responstijd van de applicatie.
Belangrijkste punten
RenderObject Tree — is een hiërarchische structuur van weergave-objecten die de daadwerkelijke representatie van de interface in het geheugen is. Elke RenderObject kent zijn afmetingen, positie op het scherm en kan zichzelf tekenen. In tegenstelling tot widgets, die lichtgewicht zijn en honderden keren per seconde opnieuw kunnen worden aangemaakt, is RenderObject — een zwaar object met directe toegang tot de grafische pijplijn.
Het pad van widget naar pixels doorloopt drie fasen: Widget Tree beschrijft wat er op het scherm moet zijn; Element Tree beheert de levenscyclus; RenderObject Tree voert het daadwerkelijke werk uit. Elke RenderObjectWidget (bijv. Padding, Transform, CustomPaint) maakt een RenderObject die aan de weergaveboom wordt toegevoegd. RenderBox — het meest gebruikte type RenderObject, gebruikt voor 99% van de standaard widgets.
RenderObject — is een abstracte klasse die de interface voor layout en paint definieert. Het bevat verwijzingen naar de bovenliggende RenderObject en onderliggende objecten, evenals abstracte methoden: performLayout, paint en hitTest. Elke concrete RenderObject implementeert deze methoden volgens zijn gedrag: RenderFlex verdeelt ruimte tussen onderliggende elementen, RenderImage geeft een afbeelding weer, RenderParagraph geeft tekst weer.
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
In deze vereenvoudigde structuur bevat RenderObject de vlaggen _needsLayout en _needsPaint die het object markeren als update-behoeftig. Wanneer Widget Tree verandert, markeert Element Tree de corresponderende RenderObjects als „vuil„ voor layout of paint, en bij het volgende frame voert Flutter alleen de noodzakelijke bewerkingen uit.
Elke RenderObject voert twee cruciale fasen uit: layout (bepalen van afmetingen en posities) en paint (tekenen). Deze fasen worden in strikte volgorde uitgevoerd: eerst layout voor de hele boom, dan paint. De paint-fase kan worden overgeslagen als layout niet is gewijzigd, wat GPU-bronnen bespaart.
Tijdens layout geeft Flutter beperkingen (constraints) van boven naar beneden door de RenderObject Tree. Elke ouder stelt voor het onderliggende object de minimale en maximale breedte en hoogte in. Het onderliggende object berekent zijn afmeting binnen deze beperkingen en retourneert deze aan de ouder. Dit proces wordt „downward pass„ (beperkingen doorgeven naar beneden) en „upward pass„ (afmetingen doorgeven naar boven) genoemd.
Na voltooiing van layout voert Flutter paint uit — het tekenen van elke RenderObject. De ouder maakt een PaintingContext, geeft deze door aan onderliggende objecten en specificeert de offset. Elke RenderObject tekent zichzelf op het Canvas met behulp van grafische primitieven: rechthoeken, cirkels, tekst, afbeeldingen en transformaties. Canvas communiceert rechtstreeks met Skia of Impeller.
Flutter gebruikt het mechanisme van „vuile„ knooppunten om werk te minimaliseren. Wanneer alleen de afmeting van één RenderObject verandert, berekent Flutter niet de layout van de hele boom opnieuw — het markeert het gewijzigde knooppunt en zijn mogelijke voorouders tot de dichtstbijzijnde RenderBox met vaste afmeting. Bij wijziging van het uiterlijk wordt alleen paint gemarkeerd, zonder herhaling van layout.
Flutter biedt verschillende categorieën RenderObject voor verschillende taken: RenderBox voor standaard rechthoekige elementen, RenderSliver voor scrollbare gebieden en aangepaste RenderObject voor niet-standaard weergave via CustomPainter. Elk type is geoptimaliseerd voor zijn rol in de weergaveboom.
RenderBox — de basisklasse voor rechthoekige interface-elementen. Zijn subtypes: RenderPadding (voegt ruimte toe), RenderTransform (past transformaties toe), RenderFlex (implementeert Row en Column), RenderStack (stapelen van elementen), RenderImage (weergave van afbeeldingen), RenderParagraph (weergave van tekst). Elk subtype overschrijft performLayout en paint voor zijn eigen logica.
RenderSliver — is een type RenderObject voor het werken met scrollbare gebieden. In tegenstelling tot RenderBox gebruikt Sliver SliverConstraints die informatie over het zichtbare gebied (viewport) bevatten. RenderSliverList en RenderSliverGrid maken alleen RenderObject voor elementen die in het zichtbare gebied vallen, waardoor lijsten met miljoenen records kunnen worden verwerkt.
Voor niet-standaard grafische afbeeldingen gebruikt u CustomPaint en CustomPainter. CustomPaint maakt RenderCustomPaint die de paint-methoden in CustomPainter aanroept. Hiermee kunt u willekeurige vormen, grafieken en animaties tekenen met volledige controle over Canvas. Volgens Flutter Team is CustomPainter efficiënter dan geneste standaard widgets voor complexe vectorafbeeldingen.
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color;
canvas.drawCircle(
Offset(size.width / 2, size.height / 2),
size.width / 3,
paint,
);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
In dit voorbeeld tekent CirclePainter een cirkel op Canvas. De methode shouldRepaint retourneert alleen true bij kleurwijziging, wat onnodig hertekenen voorkomt. CustomPainter moet zo licht mogelijk zijn — alle zware berekeningen voert u buiten de paint-methoden uit.
RenderObject Tree wordt gemaakt uit Element Tree via het mechanisme RenderObjectWidget. Elke RenderObjectWidget (Padding, Transform, CustomPaint) maakt een RenderObjectElement dat de bijbehorende RenderObject aanmaakt en beheert. Het element fungeert als tussenpersoon: het geeft de configuratie van de widget door aan de RenderObject en stelt de RenderObject op de hoogte van wijzigingen.
Wanneer RenderObjectElement wordt gemonteerd, roept het de methode createRenderObject van zijn widget aan. De widget maakt een instantie van RenderObject en retourneert deze aan het element. Het element plaatst de RenderObject in RenderObject Tree door de methode insertChildLayout van de bovenliggende RenderObject aan te roepen. Dit proces vindt alleen plaats bij de eerste montage — bij volgende updates werkt het element eenvoudigweg de parameters van de bestaande RenderObject bij.
Wanneer de configuratie van de widget verandert (bijv. de padding-waarde verandert), roept het element de methode updateRenderObject aan, die de nieuwe configuratie aan de bestaande RenderObject doorgeeft. RenderObject markeert zichzelf als „vuil„ voor layout of paint, en bij het volgende frame voert het framework de nodige updates uit.
Bij het demonteren van het element wordt de methode unmount aangeroepen, die de RenderObject uit RenderObject Tree verwijdert en bronnen vrijgeeft. RenderObject.remove wordt aangeroepen om los te koppelen van de ouder, waarna het object door de garbage collector kan worden opgehaald. Flutter garandeert dat RenderObject niet in de boom blijft hangen zonder het bijbehorende element.
RepaintBoundary — is een widget die een aparte laag creëert voor de weergave van zijn inhoud. Wanneer de inhoud van RepaintBoundary verandert, wordt alleen deze laag hertekend en blijven de overige delen van het scherm ongewijzigd. RepaintBoundary is vooral nuttig voor animaties, videospelers, interactieve grafieken en andere veelvuldig bijgewerkte elementen.
Aan de basis van RepaintBoundary ligt RenderRepaintBoundary — een speciale RenderObject die een aparte PictureLayer maakt. Bij de eerste weergave registreert RenderRepaintBoundary de grafische opdrachten in deze laag. Bij volgende updates, als alleen de inhoud binnen RepaintBoundary is gewijzigd, hertekent Flutter alleen deze laag, niet het hele scherm. De andere lagen blijven ongewijzigd en worden opnieuw gebruikt.
Niet elke widget heeft RepaintBoundary nodig. Gebruik het wanneer een deel van de interface met hoge frequentie (60 FPS en hoger) wordt bijgewerkt en de rest van het scherm statisch is. Typische voorbeelden: geanimeerde laadindicator, videospeler, game Canvas, CustomPainter met frequente hertekening. Voor statische tekst of knoppen is RepaintBoundary overbodig en verhoogt het alleen het geheugengebruik.
| Scenario | Aanbeveling | Reden |
|---|---|---|
| Animatie | Inpakken in RepaintBoundary | Isoleert veelvuldig bijgewerkt gebied |
| Scrollbare lijst | Niet nodig | ListView gebruikt automatisch lagen |
| Statische tekst | Niet nodig | Geen frequente hertekeningen |
| CustomPainter | Aanbevolen | Frequente hertekening van grafische afbeeldingen |
Prestaties van RenderObject Tree zijn afhankelijk van het aantal knooppunten, de diepte van de boom en de frequentie van hertekeningen. De tools van Flutter DevTools (tabblad „Rendering„) maken realtime analyse van RenderObject Tree mogelijk: aantal repaints, tijd van layout en paint, aantal lagen en hun afmetingen. Regelmatige analyse helpt knelpunten te identificeren.
Overdraw — is een situatie waarin één pixel meerdere keren per frame wordt getekend. Bijvoorbeeld, wanneer een halfdoorzichtige widget over een andere wordt geplaatst, tekent de GPU beide lagen. Gebruik opaque-vlaggen (Container met color in plaats van decoration) voor ondoorzichtige elementen, zodat Flutter onzichtbare lagen overslaat. Volgens Flutter Team kan vermindering van overdraw de paint-tijd met tot 30% verkorten.
Elke RepaintBoundary en sommige widgets (Opacity, ClipRRect, Transform) maken een aparte laag (PictureLayer). Te veel lagen verhogen de compositietijd. Gebruik groepering: in plaats van meerdere Opacity op afzonderlijke widgets, past u één Opacity toe op een container. In plaats van ClipRRect op elk element, gebruikt u ClipRRect op een gemeenschappelijke container.
Wanneer een widget als const wordt gedeclareerd, weet Flutter dat de configuratie niet zal veranderen en kan de bijbehorende RenderObject opnieuw worden gebruikt zonder opnieuw aanmaken. Const-constructors verminderen de belasting van de garbage collector en versnellen het eerste frame. Gebruik const voor widgets met vaste parameters: pictogrammen, titels, decoratieve elementen.
const Text("Titel", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
Veelgestelde vragen
Widget Tree — is een lichte interfaceconfiguratie die bij elke rebuild opnieuw wordt aangemaakt. RenderObject Tree — is een zware boom van weergave-objecten die wordt bewaard en alleen wordt bijgewerkt bij wijziging van geometrie of uiterlijk.
Gebruik Flutter DevTools — tabblad „Rendering„. U ziet de weergavelagen, tijd van layout en paint, evenals gedetailleerde informatie over elke RenderObject: afmetingen, constraints, vlaggen voor update-behoefte.
Dirty — is een RenderObject die is gemarkeerd als update-behoeftig. De vlag _needsLayout of _needsPaint wordt ingesteld bij wijziging van configuratie, en Flutter voert layout of paint voor dit knooppunt uit in het volgende frame.
Ja, maak een subclass van RenderBox en overschrijf de methoden performLayout en paint. Gebruik RenderObjectWidget om de aangepaste RenderObject in Widget Tree te plaatsen. Dit is een geavanceerde techniek voor niet-standaard weergave.
RepaintBoundary maakt RenderRepaintBoundary die een deel van RenderObject Tree isoleert in een aparte laag. Bij wijziging van de inhoud wordt alleen deze laag hertekend en de rest van de boom blijft ongewijzigd.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook