RenderObject Tree — je třetí úroveň hierarchie ve Flutter, zodpovědná za skutečné vykreslování rozhraní na obrazovce. Každý uzel tohoto stromu provádí výpočet rozměrů (layout) a kreslení (painting), převádějící konfiguraci widgetů na pixely. Na rozdíl od Widget Tree je RenderObject Tree vytvořen jednou a aktualizuje se pouze při změně geometrie nebo vzhledu. Podle Flutter API Reference, 2025 efektivita RenderObject Tree přímo určuje plynulost animací a rychlost odezvy aplikace.
Hlavní body
RenderObject Tree — je hierarchická struktura objektů vykreslování, která je skutečnou reprezentací rozhraní v paměti. Každý RenderObject zná své rozměry, polohu na obrazovce a umí se nakreslit. Na rozdíl od widgetů, které jsou lehké a mohou být znovu vytvářeny stokrát za sekundu, RenderObject — je těžký objekt s přímým přístupem ke grafické pipeline.
Cesta od widgetu k pixelům prochází třemi fázemi: Widget Tree popisuje, co by mělo být na obrazovce; Element Tree spravuje životní cyklus; RenderObject Tree provádí skutečnou práci. Každý RenderObjectWidget (např. Padding, Transform, CustomPaint) vytváří RenderObject, který je přidán do stromu vykreslování. RenderBox — nejrozšířenější typ RenderObject, používaný pro 99% standardních widgetů.
RenderObject — je abstraktní třída definující rozhraní pro layout a paint. Obsahuje odkazy na rodičovský RenderObject a podřízené objekty, stejně jako abstraktní metody: performLayout, paint a hitTest. Každý konkrétní RenderObject implementuje tyto metody podle svého chování: RenderFlex rozděluje prostor mezi podřízené prvky, RenderImage zobrazuje obrázek, RenderParagraph zobrazuje text.
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
V této zjednodušené struktuře obsahuje RenderObject příznaky _needsLayout a _needsPaint, které označují objekt jako vyžadující aktualizaci. Když se Widget Tree změní, Element Tree označí odpovídající RenderObject jako „špinavý„ pro layout nebo paint a při příštím snímku Flutter provede pouze nezbytné operace.
Každý RenderObject provádí dvě klíčové fáze: layout (určení rozměrů a pozic) a paint (kreslení). Tyto fáze se provádějí v přísném pořadí: nejprve layout pro celý strom, poté paint. Fáze paint může být vynechána, pokud se layout nezměnil, což šetří prostředky GPU.
Během layoutu Flutter předává omezení (constraints) shora dolů přes RenderObject Tree. Každý rodič nastavuje pro podřízený objekt minimální a maximální šířku a výšku. Podřízený objekt vypočítá svou velikost v rámci těchto omezení a vrátí ji rodiči. Tento proces se nazývá „downward pass„ (předávání omezení dolů) a „upward pass„ (předávání rozměrů nahoru).
Po dokončení layoutu Flutter provede paint — kreslení každého RenderObject. Rodič vytvoří PaintingContext, předá ho podřízeným objektům a určí posun (offset). Každý RenderObject se kreslí na Canvas pomocí grafických primitiv: obdélníky, kruhy, text, obrázky a transformace. Canvas přímo komunikuje s Skia nebo Impeller.
Flutter používá mechanismus „špinavých„ uzlů k minimalizaci práce. Když se změní pouze velikost jednoho RenderObject, Flutter nepřepočítává layout celého stromu — označí změněný uzel a jeho možné předky až k nejbližšímu RenderBox s pevnou velikostí. Podobně při změně vzhledu se označí pouze paint bez opakování layoutu.
Flutter poskytuje několik kategorií RenderObject pro různé úkoly: RenderBox pro standardní obdélníkové prvky, RenderSliver pro posouvatelné oblasti a vlastní RenderObject pro nestandardní vykreslování přes CustomPainter. Každý typ je optimalizován pro svou roli ve stromu vykreslování.
RenderBox — základní třída pro obdélníkové prvky rozhraní. Jeho podtypy: RenderPadding (přidává mezery), RenderTransform (aplikuje transformace), RenderFlex (implementuje Row a Column), RenderStack (vrstvení prvků), RenderImage (zobrazení obrázků), RenderParagraph (zobrazení textu). Každý podtyp přepisuje performLayout a paint pro svou logiku.
RenderSliver — je typ RenderObject pro práci s posouvatelnými oblastmi. Na rozdíl od RenderBox používá Sliver SliverConstraints, které zahrnují informace o viditelné oblasti (viewport). RenderSliverList a RenderSliverGrid vytvářejí RenderObject pouze pro prvky ve viditelné oblasti, což umožňuje zpracování seznamů s miliony záznamů.
Pro nestandardní grafiku použijte CustomPaint a CustomPainter. CustomPaint vytváří RenderCustomPaint, který volá metody paint v CustomPainter. To umožňuje kreslení libovolných tvarů, grafů a animací s plnou kontrolou nad Canvas. Podle Flutter Team je CustomPainter efektivnější než vnořené standardní widgety pro komplexní vektorovou grafiku.
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;
}
V tomto příkladu CirclePainter kreslí kruh na Canvas. Metoda shouldRepaint vrací true pouze při změně barvy, což zabraňuje zbytečnému překreslování. CustomPainter by měl být co nejlehčí — všechny těžké výpočty provádějte mimo metody paint.
RenderObject Tree je vytvořen z Element Tree prostřednictvím mechanismu RenderObjectWidget. Každý RenderObjectWidget (Padding, Transform, CustomPaint) vytváří RenderObjectElement, který vytváří a spravuje odpovídající RenderObject. Prvek funguje jako prostředník: předává konfiguraci z widgetu do RenderObject a informuje RenderObject o změnách.
Když je RenderObjectElement připojen, zavolá metodu createRenderObject svého widgetu. Widget vytvoří instanci RenderObject a vrátí ji prvku. Prvek vloží RenderObject do RenderObject Tree zavoláním metody insertChildLayout u rodičovského RenderObject. Tento proces probíhá pouze při prvním připojení — při následných aktualizacích prvek jednoduše aktualizuje parametry existujícího RenderObject.
Když se konfigurace widgetu změní (např. změní se hodnota padding), prvek zavolá metodu updateRenderObject, která předá novou konfiguraci existujícímu RenderObject. RenderObject se označí jako „špinavý„ pro layout nebo paint a při příštím snímku framework provede potřebné aktualizace.
Při odpojení prvku se zavolá metoda unmount, která odstraní RenderObject z RenderObject Tree a uvolní prostředky. RenderObject.remove se volá pro odpojení od rodiče, poté může být objekt shromážděn garbage collectorem. Flutter zaručuje, že RenderObject nevisí ve stromu bez odpovídajícího prvku.
RepaintBoundary — je widget, který vytváří samostatnou vrstvu pro vykreslování svého obsahu. Když se obsah RepaintBoundary změní, překreslí se pouze tato vrstva a ostatní části obrazovky zůstanou nezměněny. RepaintBoundary je zvláště užitečný pro animace, přehrávače videa, interaktivní grafy a další často aktualizované prvky.
Základem RepaintBoundary je RenderRepaintBoundary — speciální RenderObject, který vytváří samostatný PictureLayer. Při prvním vykreslení RenderRepaintBoundary zaznamená grafické příkazy do této vrstvy. Při následných aktualizacích, pokud se změnil pouze obsah uvnitř RepaintBoundary, Flutter překreslí pouze tuto vrstvu, ne celou obrazovku. Ostatní vrstvy zůstávají nezměněny a jsou znovu použity.
Ne každý widget potřebuje RepaintBoundary. Použijte ho, když se část rozhraní aktualizuje s vysokou frekvencí (60 FPS a více), zatímco zbytek obrazovky je statický. Typické příklady: animovaný indikátor načítání, přehrávač videa, herní Canvas, CustomPainter s častým překreslováním. Pro statický text nebo tlačítka je RepaintBoundary zbytečný a pouze zvyšuje spotřebu paměti.
| Scénář | Doporučení | Důvod |
|---|---|---|
| Animace | Zabalit do RepaintBoundary | Izoluje často aktualizovanou oblast |
| Posouvatelný seznam | Není nutné | ListView automaticky používá vrstvy |
| Statický text | Není nutné | Žádné časté překreslování |
| CustomPainter | Doporučeno | Časté překreslování grafiky |
Výkon RenderObject Tree závisí na počtu uzlů, hloubce stromu a frekvenci překreslování. Nástroje Flutter DevTools (karta „Rendering„) umožňují analýzu RenderObject Tree v reálném čase: počet repaint, čas layout a paint, počet vrstev a jejich velikosti. Pravidelná analýza pomáhá identifikovat úzká místa.
Overdraw — je situace, kdy je jeden pixel kreslen několikrát za snímek. Například když se poloprůhledný widget překrývá s jiným, GPU kreslí obě vrstvy. Používejte opaque příznaky (Container s color místo decoration) pro neprůhledné prvky, aby Flutter přeskočil neviditelné vrstvy. Podle Flutter Team může snížení overdraw zkrátit čas paint až o 30%.
Každý RepaintBoundary a některé widgety (Opacity, ClipRRect, Transform) vytvářejí samostatnou vrstvu (PictureLayer). Příliš mnoho vrstev zvyšuje čas kompozice. Používejte seskupování: místo několika Opacity na jednotlivých widgetech aplikujte jeden Opacity na kontejner. Místo ClipRRect na každém prvku použijte ClipRRect na společném kontejneru.
Když je widget deklarován jako const, Flutter ví, že se jeho konfigurace nezmění a může znovu použít odpovídající RenderObject bez znovuvytvoření. Const-konstruktory snižují zatížení garbage collectoru a zrychlují první snímek. Používejte const pro widgety s pevnými parametry: ikony, nadpisy, dekorativní prvky.
const Text("Název", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
Často kladené otázky
Widget Tree — je lehká konfigurace rozhraní, která se znovu vytváří při každém rebuild. RenderObject Tree — je těžký strom objektů vykreslování, který je zachován a aktualizuje se pouze při změně geometrie nebo vzhledu.
Použijte Flutter DevTools — karta „Rendering„. Uvidíte vrstvy vykreslování, čas layout a paint, stejně jako podrobné informace o každém RenderObject: rozměry, constraints, příznaky potřeby aktualizace.
Dirty — je RenderObject, který je označen jako vyžadující aktualizaci. Příznak _needsLayout nebo _needsPaint se nastaví při změně konfigurace a Flutter provede layout nebo paint pro tento uzel v příštím snímku.
Ano, vytvořte podtřídu RenderBox a přepište metody performLayout a paint. Použijte RenderObjectWidget pro vložení vlastního RenderObject do Widget Tree. Toto je pokročilá technika pro nestandardní vykreslování.
RepaintBoundary vytváří RenderRepaintBoundary, který izoluje část RenderObject Tree do samostatné vrstvy. Při změně obsahu se překreslí pouze tato vrstva a zbytek stromu zůstane nezměněn.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také