RenderObject Tree — är den tredje nivån i hierarkin i Flutter, ansvarig för den faktiska renderingen av gränssnittet på skärmen. Varje nod i detta träd utför beräkning av storlekar (layout) och ritning (painting), och omvandlar widget-konfigurationen till pixlar. Till skillnad från Widget Tree skapas RenderObject Tree en gång och uppdateras endast när geometrin eller utseendet ändras. Enligt Flutter API Reference, 2025 avgör effektiviteten hos RenderObject Tree direkt smidigheten i animationer och applikationens svarstid.
Huvudpunkter
RenderObject Tree — är en hierarkisk struktur av renderingsobjekt som är den faktiska representationen av gränssnittet i minnet. Varje RenderObject känner till sina storlekar, position på skärmen och kan rita sig själv. Till skillnad från widgets, som är lätta och kan återskapas hundratals gånger per sekund, är RenderObject — ett tungt objekt med direkt åtkomst till grafikpipelinen.
Vägen från widget till pixlar går igenom tre steg: Widget Tree beskriver vad som ska finnas på skärmen; Element Tree hanterar livscykeln; RenderObject Tree utför det faktiska arbetet. Varje RenderObjectWidget (t.ex. Padding, Transform, CustomPaint) skapar en RenderObject som läggs till i renderingsträdet. RenderBox — den vanligaste typen av RenderObject, som används för 99% av standardwidgets.
RenderObject — är en abstrakt klass som definierar gränssnittet för layout och paint. Den innehåller referenser till förälder-RenderObject och barnobjekt, samt abstrakta metoder: performLayout, paint och hitTest. Varje konkret RenderObject implementerar dessa metoder enligt sitt beteende: RenderFlex fördelar utrymme mellan barn-element, RenderImage visar bild, RenderParagraph visar text.
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
I denna förenklade struktur innehåller RenderObject flaggorna _needsLayout och _needsPaint som markerar objektet som uppdateringsbehövande. När Widget Tree ändras, markerar Element Tree motsvarande RenderObjects som "smutsiga" för layout eller paint, och vid nästa bildruta utför Flutter endast nödvändiga operationer.
Varje RenderObject utför två nyckelfaser: layout (bestämning av storlekar och positioner) och paint (ritning). Dessa faser utförs i strikt ordning: först layout för hela trädet, sedan paint. Paint-fasen kan hoppas över om layout inte har ändrats, vilket sparar GPU-resurser.
Under layout skickar Flutter begränsningar (constraints) uppifrån och ner genom RenderObject Tree. Varje förälder ställer in för barnobjektet minimal och maximal bredd och höjd. Barnobjektet beräknar sin storlek inom dessa begränsningar och returnerar den till föräldern. Denna process kallas "downward pass" (överföring av begränsningar nedåt) och "upward pass" (överföring av storlekar uppåt).
Efter slutförd layout utför Flutter paint — ritning av varje RenderObject. Föräldern skapar en PaintingContext, skickar den till barnobjekten och anger offset. Varje RenderObject ritar sig själv på Canvas med hjälp av grafiska primitiver: rektanglar, cirklar, text, bilder och transformationer. Canvas interagerar direkt med Skia eller Impeller.
Flutter använder mekanismen med "smutsiga" noder för att minimera arbete. När endast storleken på en RenderObject ändras, beräknar Flutter inte om layout för hela trädet — det markerar den ändrade noden och dess möjliga förfäder fram till närmaste RenderBox med fast storlek. På liknande sätt, när utseendet ändras, markeras endast paint utan upprepning av layout.
Flutter tillhandahåller flera kategorier av RenderObject för olika uppgifter: RenderBox för standard rektangulära element, RenderSliver för rullningsbara områden och anpassad RenderObject för icke-standard rendering via CustomPainter. Varje typ är optimerad för sin roll i renderingsträdet.
RenderBox — basklassen för rektangulära gränssnittselement. Dess undertyper: RenderPadding (lägger till mellanrum), RenderTransform (tillämpar transformationer), RenderFlex (implementerar Row och Column), RenderStack (stapling av element), RenderImage (visning av bilder), RenderParagraph (visning av text). Varje undertyp åsidosätter performLayout och paint för sin egen logik.
RenderSliver — är en typ av RenderObject för arbete med rullningsbara områden. Till skillnad från RenderBox använder Sliver SliverConstraints som inkluderar information om det synliga området (viewport). RenderSliverList och RenderSliverGrid skapar RenderObject endast för element som finns i det synliga området, vilket möjliggör bearbetning av listor med miljontals poster.
För icke-standard grafik, använd CustomPaint och CustomPainter. CustomPaint skapar RenderCustomPaint som anropar paint-metoderna i CustomPainter. Detta möjliggör ritning av godtyckliga former, diagram och animationer med full kontroll över Canvas. Enligt Flutter Team är CustomPainter effektivare än nästlade standardwidgets för komplex vektorgrafik.
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;
}
I detta exempel ritar CirclePainter en cirkel på Canvas. Metoden shouldRepaint returnerar true endast vid färgförändring, vilket förhindrar onödig omritning. CustomPainter bör vara så lätt som möjligt — alla tunga beräkningar utför du utanför paint-metoderna.
RenderObject Tree skapas från Element Tree genom mekanismen RenderObjectWidget. Varje RenderObjectWidget (Padding, Transform, CustomPaint) skapar ett RenderObjectElement som skapar och hanterar motsvarande RenderObject. Elementet fungerar som förmedlare: det skickar konfigurationen från widgeten till RenderObject och meddelar RenderObject om ändringar.
När RenderObjectElement monteras anropar det widgetens createRenderObject-metod. Widgeten skapar en instans av RenderObject och returnerar den till elementet. Elementet bäddar in RenderObject i RenderObject Tree genom att anropa metoden insertChildLayout hos förälder-RenderObject. Denna process sker endast vid första monteringen — vid efterföljande uppdateringar uppdaterar elementet helt enkelt parametrarna för den befintliga RenderObject.
När widgetens konfiguration ändras (t.ex. padding-värdet ändras), anropar elementet updateRenderObject-metoden, som skickar den nya konfigurationen till den befintliga RenderObject. RenderObject markerar sig själv som "smutsig" för layout eller paint, och vid nästa bildruta utför ramverket nödvändiga uppdateringar.
Vid avmontering av elementet anropas unmount-metoden, som tar bort RenderObject från RenderObject Tree och frigör resurser. RenderObject.remove anropas för att koppla bort från föräldern, varefter objektet kan samlas in av soprensaren. Flutter garanterar att RenderObject inte hänger kvar i trädet utan motsvarande element.
RepaintBoundary — är en widget som skapar ett separat lager för rendering av sitt innehåll. När innehållet i RepaintBoundary ändras, ritas endast detta lager om och resten av skärmen förblir oförändrad. RepaintBoundary är särskilt användbart för animationer, videospelare, interaktiva diagram och andra ofta uppdaterade element.
Grunden för RepaintBoundary är RenderRepaintBoundary — en speciell RenderObject som skapar ett separat PictureLayer. Vid första renderingen registrerar RenderRepaintBoundary grafikkommandon i detta lager. Vid efterföljande uppdateringar, om endast innehållet inuti RepaintBoundary har ändrats, ritar Flutter endast om detta lager, inte hela skärmen. De andra lagren förblir oförändrade och återanvänds.
Inte varje widget behöver RepaintBoundary. Använd det när en del av gränssnittet uppdateras med hög frekvens (60 FPS och högre), medan resten av skärmen är statisk. Typiska exempel: animerad laddningsindikator, videospelare, spel-Canvas, CustomPainter med frekvent omritning. För statisk text eller knappar är RepaintBoundary överflödigt och ökar endast minnesförbrukningen.
| Scenario | Rekommendation | Anledning |
|---|---|---|
| Animation | Slå in i RepaintBoundary | Isolerar ofta uppdaterat område |
| Rullningsbar lista | Behövs inte | ListView använder automatiskt lager |
| Statisk text | Behövs inte | Inga frekventa omritningar |
| CustomPainter | Rekommenderas | Frekvent omritning av grafik |
Prestanda för RenderObject Tree beror på antalet noder, trädets djup och frekvensen av omritningar. Verktygen i Flutter DevTools (fliken "Rendering") möjliggör realtidsanalys av RenderObject Tree: antal repaint, tid för layout och paint, antal lager och deras storlekar. Regelbunden analys hjälper till att identifiera flaskhalsar.
Overdraw — är en situation där en pixel ritas flera gånger per bildruta. Till exempel, när en halvgenomskinlig widget placeras över en annan, ritar GPU båda lagren. Använd opaque-flaggor (Container med color istället för decoration) för ogenomskinliga element så att Flutter hoppar över osynliga lager. Enligt Flutter Team kan minskning av overdraw förkorta paint-tiden med upp till 30%.
Varje RepaintBoundary och vissa widgets (Opacity, ClipRRect, Transform) skapar ett separat lager (PictureLayer). För många lager ökar kompositionstiden. Använd gruppering: istället för flera Opacity på separata widgets, applicera en Opacity på en container. Istället för ClipRRect på varje element, använd ClipRRect på en gemensam container.
När en widget deklareras som const, vet Flutter att dess konfiguration inte kommer att ändras och kan återanvända motsvarande RenderObject utan att skapa om. Const-konstruktorer minskar belastningen på soprensaren och påskyndar den första bildrutan. Använd const för widgets med fasta parametrar: ikoner, rubriker, dekorativa element.
const Text("Titel", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
Vanliga frågor
Widget Tree — är en lätt gränssnittskonfiguration som återskapas vid varje rebuild. RenderObject Tree — är ett tungt träd av renderingsobjekt som bevaras och uppdateras endast när geometrin eller utseendet ändras.
Använd Flutter DevTools — fliken "Rendering". Du ser renderingslager, tid för layout och paint, samt detaljerad information om varje RenderObject: storlekar, constraints, flaggor för uppdateringsbehov.
Dirty — är en RenderObject som markerats som uppdateringsbehövande. Flaggorna _needsLayout eller _needsPaint sätts när konfigurationen ändras, och Flutter utför layout eller paint för denna nod i nästa bildruta.
Ja, skapa en underklass till RenderBox och åsidosätt metoderna performLayout och paint. Använd RenderObjectWidget för att bädda in den anpassade RenderObject i Widget Tree. Detta är en avancerad teknik för icke-standard rendering.
RepaintBoundary skapar RenderRepaintBoundary som isolerar en del av RenderObject Tree i ett separat lager. När innehållet ändras ritas endast detta lager om och resten av trädet förblir oförändrat.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också