RenderObject Tree — Flutter-də iyerarxiyanın üçüncü səviyyəsidir, interfeysin ekranda faktiki göstərilməsinə cavabdehdir. Bu ağacın hər bir qovşağı ölçülərin hesablanması (layout) və rəsm çəkmə (painting) yerinə yetirir, vidjet konfiqurasiyasını piksellərə çevirir. Widget Tree-dən fərqli olaraq, RenderObject Tree bir dəfə yaradılır və yalnız həndəsə və ya görünüş dəyişdikdə yenilənir. Flutter API Reference, 2025 məlumatlarına görə, RenderObject Tree-nin səmərəliliyi animasiyaların hamarlığını və tətbiqin cavab sürətini birbaşa müəyyən edir.
Əsas məqamlar
RenderObject Tree — interfeysin yaddaşda faktiki təmsili olan göstərmə obyektlərinin iyerarxik strukturudur. Hər RenderObject öz ölçülərini, ekrandakı mövqeyini bilir və özünü çəkə bilir. Saniyədə yüzlərlə dəfə yenidən yaradıla bilən yüngül vidjetlərdən fərqli olaraq, RenderObject — qrafik konveyerə birbaşa çıxışı olan ağır obyektdir.
Vidjetdən piksellərə yol üç mərhələdən keçir: Widget Tree ekranda nə olması lazım olduğunu təsvir edir; Element Tree həyat dövrünü idarə edir; RenderObject Tree faktiki işi yerinə yetirir. Hər RenderObjectWidget (məsələn, Padding, Transform, CustomPaint) göstərmə ağacına əlavə olunan RenderObject yaradır. RenderBox — standart vidjetlərin 99%-i üçün istifadə olunan ən geniş yayılmış RenderObject növüdür.
RenderObject — layout və paint üçün interfeys müəyyən edən abstrakt sinifdir. O, valideyn RenderObject və uşaq obyektlərinə istinadları, həmçinin abstrakt metodları ehtiva edir: performLayout, paint və hitTest. Hər konkret RenderObject bu metodları öz davranışına uyğun həyata keçirir: RenderFlex uşaq elementlər arasında yer paylayır, RenderImage şəkil göstərir, RenderParagraph mətn göstərir.
abstract class RenderObject {
RenderObject? parent;
Constraints constraints;
ParentData? parentData;
bool _needsLayout = true;
bool _needsPaint = true;
void performLayout();
void paint(PaintingContext context, Offset offset);
}
Bu sadələşdirilmiş strukturda RenderObject _needsLayout və _needsPaint bayraqlarını ehtiva edir ki, bu da obyekti yenilənmə tələb edən kimi qeyd edir. Widget Tree dəyişdikdə, Element Tree müvafiq RenderObject-u layout və ya paint üçün "çirkli" olaraq qeyd edir və növbəti kadrda Flutter yalnız zəruri əməliyyatları yerinə yetirir.
Hər RenderObject iki əsas faza yerinə yetirir: layout (ölçü və mövqelərin müəyyən edilməsi) və paint (çəkmə). Bu fazalar ciddi qaydada yerinə yetirilir: əvvəlcə bütün ağac üçün layout, sonra paint. Layout dəyişməyibsə, paint fazası buraxıla bilər ki, bu da GPU resurslarına qənaət edir.
Layout zamanı Flutter RenderObject Tree boyunca yuxarıdan aşağıya məhdudiyyətlər (constraints) ötürür. Hər valideyn uşaq obyekt üçün minimum və maksimum en və hündürlük təyin edir. Uşaq obyekt bu məhdudiyyətlər çərçivəsində öz ölçüsünü hesablayır və valideynə qaytarır. Bu proses "downward pass" (məhdudiyyətlərin aşağı ötürülməsi) və "upward pass" (ölçülərin yuxarı ötürülməsi) adlanır.
Layout tamamlandıqdan sonra Flutter paint — hər RenderObject-un çəkilməsini yerinə yetirir. Valideyn PaintingContext yaradır, onu uşaq obyektlərə ötürür və yerdəyişməni (offset) göstərir. Hər RenderObject Canvas üzərində qrafik primitivlərdən istifadə edərək özünü çəkir: düzbucaqlılar, dairələr, mətn, şəkillər və transformasiyalar. Canvas birbaşa Skia və ya Impeller ilə qarşılıqlı əlaqədə olur.
Flutter işi minimuma endirmək üçün "çirkli" qovşaqlar mexanizmindən istifadə edir. Yalnız bir RenderObject-un ölçüsü dəyişdikdə, Flutter bütün ağacın layoutunu yenidən hesablamır — dəyişmiş qovşağı və onun sabit ölçülü ən yaxın RenderBox-a qədər potensial əcdadlarını qeyd edir. Eynilə, görünüş dəyişdikdə, layout təkrarlanmadan yalnız paint qeyd olunur.
Flutter təmin edir müxtəlif tapşırıqlar üçün bir neçə RenderObject kateqoriyası: standart düzbucaqlı elementlər üçün RenderBox, sürüşdürülən sahələr üçün RenderSliver və CustomPainter vasitəsilə qeyri-standart göstərmə üçün fərdi RenderObject. Hər növ göstərmə ağacında öz rolu üçün optimallaşdırılmışdır.
RenderBox — düzbucaqlı interfeys elementləri üçün əsas sinifdir. Onun alt növləri: RenderPadding (boşluqlar əlavə edir), RenderTransform (transformasiyalar tətbiq edir), RenderFlex (Row və Column-u həyata keçirir), RenderStack (elementlərin üst-üstə qoyulması), RenderImage (şəkillərin göstərilməsi), RenderParagraph (mətnin göstərilməsi). Hər alt növ öz məntiqi üçün performLayout və paint-i ləğv edir.
RenderSliver — sürüşdürülən sahələrlə iş üçün RenderObject növüdür. RenderBox-dan fərqli olaraq, Sliver görünən sahə (viewport) haqqında məlumatı ehtiva edən SliverConstraints istifadə edir. RenderSliverList və RenderSliverGrid yalnız görünən sahəyə düşən elementlər üçün RenderObject yaradır ki, bu da milyonlarla qeydi olan siyahıları emal etməyə imkan verir.
Qeyri-standart qrafika üçün CustomPaint və CustomPainter istifadə edin. CustomPaint CustomPainter-də paint metodlarını çağıran RenderCustomPaint yaradır. Bu, Canvas üzərində tam nəzarətlə ixtiyari fiqurlar, qrafiklər və animasiyalar çəkməyə imkan verir. Flutter Team-in məlumatına görə, CustomPainter mürəkkəb vektor qrafikası üçün iç-içə standart vidjetlərdən daha səmərəlidir.
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;
}
Bu nümunədə CirclePainter Canvas üzərində dairə çəkir. shouldRepaint metodu yalnız rəng dəyişdikdə true qaytarır ki, bu da lazımsız yenidən çəkmənin qarşısını alır. CustomPainter mümkün qədər yüngül olmalıdır — bütün ağır hesablamaları paint metodlarından kənarda yerinə yetirin.
RenderObject Tree Element Tree-dən RenderObjectWidget mexanizmi vasitəsilə yaradılır. Hər RenderObjectWidget (Padding, Transform, CustomPaint) müvafiq RenderObject-u yaradan və idarə edən RenderObjectElement yaradır. Element vasitəçi rolunu oynayır: konfiqurasiyanı vidjetdən RenderObject-a ötürür və RenderObject-u dəyişikliklər barədə xəbərdar edir.
RenderObjectElement yerləşdirildikdə, o, öz vidjetinin createRenderObject metodunu çağırır. Vidjet RenderObject nümunəsi yaradır və onu elementə qaytarır. Element valideyn RenderObject-un insertChildLayout metodunu çağıraraq RenderObject-u RenderObject Tree-yə yerləşdirir. Bu proses yalnız ilk yerləşdirmədə baş verir — sonrakı yeniləmələrdə element sadəcə mövcud RenderObject-un parametrlərini yeniləyir.
Vidjet konfiqurasiyası dəyişdikdə (məsələn, padding dəyəri dəyişir), element updateRenderObject metodunu çağırır, bu da mövcud RenderObject-a yeni konfiqurasiya ötürür. RenderObject özünü layout və ya paint üçün "çirkli" olaraq qeyd edir və növbəti kadrda framework zəruri yeniləmələri yerinə yetirir.
Element söküldükdə unmount metodu çağırılır, bu da RenderObject-u RenderObject Tree-dən silir və resursları azad edir. Valideyndən ayrılmaq üçün RenderObject.remove çağırılır, bundan sonra obyekt zibil toplayıcısı tərəfindən yığıla bilər. Flutter RenderObject-un müvafiq elementi olmadan ağacda qalmamasını təmin edir.
RepaintBoundary — məzmununun göstərilməsi üçün ayrıca qat yaradan vidjetdir. RepaintBoundary məzmunu dəyişdikdə, yalnız bu qat yenidən çəkilir, ekranın qalan hissələri isə dəyişməz qalır. RepaintBoundary xüsusilə animasiyalar, video pleyerlər, interaktiv qrafiklər və digər tez-tez yenilənən elementlər üçün faydalıdır.
RepaintBoundary-in əsasında RenderRepaintBoundary — ayrıca PictureLayer yaradan xüsusi RenderObject dayanır. İlk göstərmədə RenderRepaintBoundary qrafik əmrlərini bu qata yazır. Sonrakı yeniləmələrdə, yalnız RepaintBoundary daxilindəki məzmun dəyişibsə, Flutter yalnız bu qatı yenidən çəkir, bütün ekranı yox. Qalan qatlar dəyişməz qalır və təkrar istifadə olunur.
Hər vidjet RepaintBoundary ehtiyac duymur. İnterfeysin bir hissəsi yüksək tezliklə (60 FPS və daha çox) yeniləndikdə, qalan ekran isə statik olduqda istifadə edin. Tipik nümunələr: animasiyalı yükləmə göstəricisi, video pleyer, oyun Canvas-ı, tez-tez yenidən çəkilən CustomPainter. Statik mətn və ya düymələr üçün RepaintBoundary artıqdır və yalnız yaddaş istehlakını artırır.
| Ssenari | Tövsiyə | Səbəb |
|---|---|---|
| Animasiya | RepaintBoundary ilə sarın | Tez-tez yenilənən sahəni təcrid edir |
| Sürüşdürülən siyahı | Tələb olunmur | ListView avtomatik qatlardan istifadə edir |
| Statik mətn | Tələb olunmur | Tez-tez yenidən çəkilmə yoxdur |
| CustomPainter | Tövsiyə olunur | Qrafikanın tez-tez yenidən çəkilməsi |
Performans RenderObject Tree qovşaqlarının sayından, ağacın dərinliyindən və yenidən çəkmə tezliyindən asılıdır. Flutter DevTools alətləri ("Rendering" sekmesi) RenderObject Tree-ni real vaxtda təhlil etməyə imkan verir: repaint sayı, layout və paint vaxtı, qatların sayı və ölçüləri. Mütəmadi təhlil dar boğazları müəyyən etməyə kömək edir.
Overdraw — bir pikselin kadr başına bir neçə dəfə çəkildiyi vəziyyətdir. Məsələn, yarı şəffaf vidjet digərinin üzərinə qoyulduqda, GPU hər iki qatı çəkir. Qeyri-şəffaf elementlər üçün opaque bayraqlarından (decoration əvəzinə color ilə Container) istifadə edin ki, Flutter görünməyən qatları keçsin. Flutter Team-in məlumatına görə, overdraw-un azaldılması paint vaxtını 30%-ə qədər qısalda bilər.
Hər RepaintBoundary və bəzi vidjetlər (Opacity, ClipRRect, Transform) ayrıca qat (PictureLayer) yaradır. Çox sayda qat kompozisiya vaxtını artırır. Qruplaşdırmadan istifadə edin: ayrı-ayrı vidjetlərdə bir neçə Opacity əvəzinə bir Opacity-ni konteynerə tətbiq edin. Hər elementdə ClipRRect əvəzinə ümumi konteynerdə ClipRRect istifadə edin.
Vidjet const olaraq elan edildikdə, Flutter onun konfiqurasiyasının dəyişməyəcəyini bilir və müvafiq RenderObject-u yenidən yaratmadan təkrar istifadə edə bilər. Const-konstruktorlar zibil toplayıcısına yükü azaldır və ilk kadrı sürətləndirir. Sabit parametrləri olan vidjetlər üçün const istifadə edin: ikonlar, başlıqlar, dekorativ elementlər.
const Text("Başlıq", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();
Tez-tez verilən suallar
Widget Tree — hər rebuild-də yenidən yaradılan yüngül interfeys konfiqurasiyasıdır. RenderObject Tree — yalnız həndəsə və ya görünüş dəyişdikdə saxlanılan və yenilənən ağır göstərmə obyektləri ağacıdır.
Flutter DevTools — "Rendering" sekmesinden istifadə edin. Göstərmə qatlarını, layout və paint vaxtını, həmçinin hər RenderObject haqqında ətraflı məlumat görəcəksiniz: ölçülər, constraints, yenilənmə ehtiyacı bayraqları.
Dirty — yenilənmə tələb edən kimi qeyd olunmuş RenderObject-dur. _needsLayout və ya _needsPaint bayrağı konfiqurasiya dəyişdikdə təyin edilir və Flutter növbəti kadrda bu qovşaq üçün layout və ya paint yerinə yetirir.
Bəli, RenderBox alt sinfi yaradın və performLayout və paint metodlarını ləğv edin. Fərdi RenderObject-u Widget Tree-yə yerləşdirmək üçün RenderObjectWidget istifadə edin. Bu, qeyri-standart göstərmə üçün qabaqcıl texnikadır.
RepaintBoundary RenderObject Tree-nin bir hissəsini ayrıca qatda təcrid edən RenderRepaintBoundary yaradır. Məzmun dəyişdikdə yalnız bu qat yenidən çəkilir, ağacın qalan hissəsi isə dəyişməz qalır.
Xülasə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun