RenderObject Tree: шта је то, принцип рендеровања и улога у Flutter-у

Аутор: IT Sectr Објављено: 2026-07-01 Време читања: 9 мин

RenderObject Tree — трећи ниво хијерархије у Flutter-у, одговоран за стварно рендеровање интерфејса на екрану. Сваки чвор овог стабла врши израчунавање димензија (layout) и цртање (painting), претварајући конфигурацију виџета у пикселе. За разлику од Widget Tree, RenderObject Tree се ствара једном и ажурира се само при промени геометрије или изгледа. Према Flutter API Reference, 2025, ефикасност RenderObject Tree директно одређује глаткоћу анимација и брзину реаговања апликације.

Главне тачке

  • RenderObject Tree — хијерархија објеката за рендеровање који израчунавају димензије и цртају интерфејс на екрану.
  • Сваки RenderObject извршава две фазе: layout (одређивање димензија и позиција) и paint (цртање пиксела).
  • RenderObject Tree се ствара из Element Tree и синхронизује се са њим преко елемената.
  • RepaintBoundary изолује део стабла за локално прецртавање без утицаја на цео екран.
  • Перформансе RenderObject Tree зависе од дубине, броја слојева и учесталости прецртавања.

Шта је RenderObject Tree у Flutter-у?

RenderObject Tree — хијерархијска структура објеката за рендеровање која је стварна репрезентација интерфејса у меморији. Сваки RenderObject зна своје димензије, положај на екрану и уме да себе нацрта. За разлику од виџета, који су лагани и могу се поново креирати стотине пута у секунди, RenderObject — тежак објекат са директним приступом графичком конвејеру.

Од конфигурације до рендеровања

Пут од виџета до пиксела пролази три фазе: Widget Tree описује шта треба да буде на екрану; Element Tree управља животним циклусом; RenderObject Tree обавља стварни посао. Сваки RenderObjectWidget (нпр. Padding, Transform, CustomPaint) креира RenderObject који се додаје у стабло рендеровања. RenderBox — најраспрострањенији тип RenderObject-а, који се користи за 99% стандардних виџета.

Архитектура RenderObject-а

RenderObject — апстрактна класа која дефинише интерфејс за layout и paint. Садржи референце на родитељски RenderObject и објекте деце, као и апстрактне методе: performLayout, paint и hitTest. Сваки конкретни RenderObject имплементира ове методе у складу са својим понашањем: RenderFlex распоређује простор између деце, RenderImage приказује слику, RenderParagraph приказује текст.

dart
abstract class RenderObject {
  RenderObject? parent;
  Constraints constraints;
  ParentData? parentData;
  bool _needsLayout = true;
  bool _needsPaint = true;

  void performLayout();
  void paint(PaintingContext context, Offset offset);
}

У овој поједностављеној структури, RenderObject садржи заставице _needsLayout и _needsPaint које означавају објекат као да захтева ажурирање. Када се Widget Tree промени, Element Tree означава одговарајуће RenderObject-е као „прљаве„ за layout или paint, и при следећем кадру Flutter извршава само неопходне операције.

Две фазе RenderObject-а: layout и paint

Сваки RenderObject извршава две кључне фазе: layout (одређивање димензија и позиција) и paint (цртање). Ове фазе се извршавају у строгом редоследу: прво layout за цело стабло, затим paint. Фаза paint може бити изостављена ако се layout није променио, чиме се штеде ресурси GPU-а.

Фаза layout: ограничења и димензије

Током layout-а, Flutter преноси ограничења (constraints) одозго наниже кроз RenderObject Tree. Сваки родитељ поставља за објекат детета минималну и максималну ширину и висину. Објекат детета израчунава своју величину у оквиру ових ограничења и враћа је родитељу. Овај процес се назива „downward pass„ (пренос ограничења наниже) и „upward pass„ (пренос димензија навише).

  • BoxConstraints — најчешћи тип ограничења: minWidth, maxWidth, minHeight, maxHeight.
  • SliverConstraints — користи се у ScrollView за виртуализацију: стандардним ограничењима се додаје информација о померању.
  • RenderSliverMultiBoxAdaptor — управља layout-ом виртуализованих листи, креирајући RenderObject само за видљиве елементе.

Фаза paint: приказ на екрану

Након завршетка layout-а, Flutter извршава paint — цртање сваког RenderObject-а. Родитељ креира PaintingContext, прослеђује га објектима деце и одређује помак (offset). Сваки RenderObject црта себе на платну Canvas, користећи графичке примитиве: правоугаонике, кругове, текст, слике и трансформације. Canvas директно комуницира са Skia или Impeller.

Обележавање прљавих чворова

Flutter користи механизам „прљавих„ чворова за минимизацију посла. Када се промени само величина једног RenderObject-а, Flutter не прерачунава layout целог стабла — означава измењени чвор и његове могуће претке до најближег RenderBox-а са фиксном величином. Слично, при промени изгледа означава се само paint, без понављања layout-а.

Типови RenderObject-а у Flutter-у

Flutter пружа неколико категорија RenderObject-а за различите задатке: RenderBox за стандардне правоугаоне елементе, RenderSliver за области за померање и прилагођени RenderObject за нестандардно рендеровање путем CustomPainter-а. Сваки тип је оптимизован за своју улогу у стаблу рендеровања.

RenderBox и његови подтипови

RenderBox — основна класа за правоугаоне елементе интерфејса. Његови подтипови: RenderPadding (додаје размаке), RenderTransform (примењује трансформације), RenderFlex (имплементира Row и Column), RenderStack (преклапање елемената), RenderImage (приказ слика), RenderParagraph (приказ текста). Сваки подтип преписује performLayout и paint за своју логику.

RenderSliver и виртуализација

RenderSliver — тип RenderObject-а за рад са областима за померање. За разлику од RenderBox-а, Sliver користи SliverConstraints који укључују информације о видљивој области (viewport). RenderSliverList и RenderSliverGrid креирају RenderObject само за елементе који се налазе у видљивој области, што омогућава обраду листи са милионима записа.

Прилагођени RenderObject путем CustomPainter-а

За нестандардну графику користите CustomPaint и CustomPainter. CustomPaint креира RenderCustomPaint који позива методе paint у CustomPainter-у. Ово омогућава цртање произвољних облика, графикона и анимација са потпуном контролом над Canvas-ом. Према Flutter Team, CustomPainter је ефикаснији од угнежђених стандардних виџета за сложену векторску графику.

dart
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;
}

У овом примеру, CirclePainter црта круг на Canvas-у. Метод shouldRepaint враћа true само при промени боје, што спречава непотребно прецртавање. CustomPainter треба да буде што лакши — све тешке прорачуне обављајте ван метода paint.

RenderObject Tree се креира из Element Tree кроз механизам RenderObjectWidget. Сваки RenderObjectWidget (Padding, Transform, CustomPaint) креира RenderObjectElement који креира и управља одговарајућим RenderObject-ом. Елемент делује као посредник: преноси конфигурацију са виџета на RenderObject и обавештава RenderObject о променама.

Креирање RenderObject-а из елемента

Када се RenderObjectElement монтира, он позива метод createRenderObject свог виџета. Виџет креира инстанцу RenderObject-а и враћа је елементу. Елемент уграђује RenderObject у RenderObject Tree, позивајући метод insertChildLayout код родитељског RenderObject-а. Овај процес се дешава само при првом монтирању — при накнадним ажурирањима елемент једноставно ажурира параметре постојећег RenderObject-а.

Синхронизација кроз updateRenderObject

Када се конфигурација виџета промени (нпр. промени се вредност padding), елемент позива метод updateRenderObject, који преноси нову конфигурацију постојећем RenderObject-у. RenderObject себе означава као „прљав„ за layout или paint, и при следећем кадру framework врши неопходна ажурирања.

Уклањање RenderObject-а

При демонтирању елемента, позива се метод unmount, који уклања RenderObject из RenderObject Tree и ослобађа ресурсе. RenderObject.remove се позива за одвајање од родитеља, након чега објекат може бити сакупљен од стране garbage collector-а. Flutter гарантује да RenderObject не виси у стаблу без одговарајућег елемента.

RepaintBoundary и изолација рендеровања

RepaintBoundary — виџет који креира засебан слој за рендеровање свог садржаја. Када се садржај RepaintBoundary-ја промени, само овај слој се прецртава, а остали делови екрана остају непромењени. RepaintBoundary је посебно користан за анимације, видео плејере, интерактивне графиконе и друге често ажуриране елементе.

Како функционише RepaintBoundary

У основи RepaintBoundary-ја лежи RenderRepaintBoundary — посебан RenderObject који креира засебан PictureLayer. При првом рендеровању, RenderRepaintBoundary бележи графичке команде у овај слој. При накнадним ажурирањима, ако се променио само садржај унутар RepaintBoundary-ја, Flutter прецртава само овај слој, а не цео екран. Остали слојеви остају непромењени и поново се користе.

Када користити RepaintBoundary

Није сваком виџету потребан RepaintBoundary. Користите га када се део интерфејса ажурира високом учесталошћу (60 FPS и више), а остатак екрана је статичан. Типични примери: анимирани индикатор учитавања, видео плејер, игри Canvas, CustomPainter са честим прецртавањем. За статички текст или дугмад, RepaintBoundary је сувишан и само повећава потрошњу меморије.

СценариоПрепорукаРазлог
АнимацијаУмотати у RepaintBoundaryИзолује често ажурирану област
Листа за померањеНије потребноListView аутоматски користи слојеве
Статички текстНије потребноНема честих прецртавања
CustomPainterПрепоручује сеЧесто прецртавање графике

Оптимизација RenderObject Tree за перформансе

Перформансе RenderObject Tree зависе од броја чворова, дубине стабла и учесталости прецртавања. Алати Flutter DevTools (картица „Rendering„) омогућавају анализу RenderObject Tree у реалном времену: број repaint-ова, време layout-а и paint-а, број слојева и њихове величине. Редовна анализа помаже у идентификацији уских грла.

Избегавајте претерани overdraw

Overdraw — ситуација када се један пиксел црта више пута по кадру. На пример, када се полупровидни виџет поставља преко другог, GPU црта оба слоја. Користите opaque заставице (Container са color уместо decoration) за непрозирне елементе како би Flutter прескочио невидљиве слојеве. Према Flutter Team, смањење overdraw-а може скратити време paint-а до 30%.

Минимизирајте број слојева

Сваки RepaintBoundary и неки виџети (Opacity, ClipRRect, Transform) креирају засебан слој (PictureLayer). Превише слојева повећава време композиције. Користите груписање: уместо више Opacity на појединачним виџетима, примените један Opacity на контејнеру. Уместо ClipRRect на сваком елементу, користите ClipRRect на заједничком контејнеру.

Користите const-конструкторе

Када је виџет декларисан као const, Flutter зна да се његова конфигурација неће променити и може поново користити одговарајући RenderObject без поновног креирања. Const-конструктори смањују оптерећење garbage collector-а и убрзавају први кадар. Користите const за виџете са фиксним параметрима: иконе, наслове, декоративне елементе.

dart
const Text("Наслов", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();

Често постављана питања

По чему се RenderObject Tree разликује од Widget Tree?

Widget Tree — лака конфигурација интерфејса која се поново креира при сваком rebuild-у. RenderObject Tree — тешко стабло објеката за рендеровање које се чува и ажурира само при промени геометрије или изгледа.

Како видети RenderObject Tree у отклањачу грешака?

Користите Flutter DevTools — картица „Rendering„. Видећете слојеве рендеровања, време layout-а и paint-а, као и детаљне информације о сваком RenderObject-у: димензије, constraints, заставице потребе за ажурирањем.

Шта је dirty RenderObject?

Dirty — RenderObject који је означен као да захтева ажурирање. Заставица _needsLayout или _needsPaint се поставља при промени конфигурације, и Flutter извршава layout или paint за овај чвор у следећем кадру.

Могу ли да креирам сопствени RenderObject?

Да, креирајте подкласу RenderBox и препишите методе performLayout и paint. Користите RenderObjectWidget за уграђивање прилагођеног RenderObject-а у Widget Tree. Ово је напредна техника за нестандардно рендеровање.

Како RepaintBoundary утиче на RenderObject Tree?

RepaintBoundary креира RenderRepaintBoundary који изолује део RenderObject Tree у засебан слој. При промени садржаја, само овај слој се прецртава, а остатак стабла остаје непромењен.

Резиме

  • RenderObject Tree — трећи ниво архитектуре Flutter-а, одговоран за layout и paint сваког елемента интерфејса.
  • Сваки RenderObject извршава две фазе: layout (израчунавање димензија и позиција) и paint (цртање пиксела кроз Canvas).
  • RenderBox — основни тип за стандардне елементе, RenderSliver — за виртуализацију листи за померање.
  • RenderObject Tree се синхронизује са Element Tree кроз RenderObjectElement који креира и ажурира RenderObject.
  • RepaintBoundary изолује део стабла у засебан слој, спречавајући потпуно прецртавање екрана при локалним променама.
  • Перформансе зависе од дубине стабла, броја слојева, overdraw-а и коришћења const-конструктора.
  • Flutter DevTools пружа алате за анализу RenderObject Tree: време layout-а, paint-а, број слојева и repaint-ова.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође