Widget / RenderObject / Lifecycle

Widget

  • levný na výrobu
  • při každém zavolání build metody se vlastně zahodí a vytvoří nový
  • je immutable
  • paralelně k widget tree existuje strom elementů a RenderObjectů
  • drží jen konfiguraci widgetu

Element

  • mutable
  • reprezentuje aktuální instanci widgetu
  • handluje life cycle widgetu a jeho závislosti ve stromu - kdo je parent, kdo je child
  • udržuje si referenci na aktuální widget a zároveň referenci na render object, který ma taky svůj strom
  • instance je pak buď StatelessElement nebo StatefullElement
  • při build metodě se volá canUpdate metoda, ktera zjišťuje jestli starý a nový widget mají stejný runtime typ a klíč (není-li klíč tak jen typ -> pokud jsou shodné tak není třeba zahazovat instanci Elementu a jen up datovat property -> je přece mutable -> tak samo se nezahodí render object -> úspora výkonu

RenderObject

  • zodpovědný za kreslení na convos

Best practices

  • části stromu, kde se odehrávají setState změny je nejlépe zabalit do custom widgetu a volat změny tam -> zmenší se scope setState a musí se updatovat menší část stromu
  • taktéž lepší custom widget než metoda tvořící strukturu widgetů -> stále patří do velkého scopu nadřazeného widgetu a updatují větší celek
  • Inherited Widget - vyvolává se přes statickou metodu get typicky
    • MediaQuery.of(context)

    • Provider.of(content)

    • toto volání nejen, že najde příslušný InheritedWidget ale zároveň zařadí volající widget do seznamu subsriberů, takže kdykoliv se v InheritedWidget změní stav, tak vyvolá rebuild i subsribovaných widgetů -> subsription dělat co nejníže ve stromu co to jde -> nebo vymezit jen oblast zájmu pokud to je InheritedModel, e.g. MediaQuery.sizeof(context) bude notifikovat jen při změně size propert

State lifecycle

stateDiagram-v2
    initState --> didChangeDependencies
    didUpdateWidget --> build
    didChangeDependencies --> build
    setState --> build
    build --> dispose

    note left of initState
      pouze jednou při mountování do stromu
    end note

    note left of didUpdateWidget
      při změně Widgetu
    end note

    note left of dispose
      při odstranění Ze stromu
    end note

    note left of didChangeDependencies
      při změně InheritedWidgetů na které jsme referencovali
    end note
  • v did metotách nevolat setState, zbytečně to duplikuje volání build metody
  • dispose musí uvolnit veškeré resourcy jako controllery, listenery, stream subscribery, jinak je garbage collector neuvolní a dojde k memory leaku
  • const třídy se stejnými argumenty budou mít v paměti pouze jednu instanci => const widget nevyvolá rebuild sebe a celého svého podstromu
  • totéž platí pokud je widget ve state třídě uložen jako final properta => odkazuje na stejné místo v paměti a framework widget ze stejné paměti nerebuilduje
  • repaintBoundary může obalit widget a říct RenderObjectu aby nešiřil needRepaint flag příliš daleko
  • Listy nejlépe přes itemBuilder a shrinkWrap = false, jinak rozbíjí 1azy loading => donutí vypočítat rozměry všech položek
    • cacheExtent definuje rozsah načteného obsahu itemBuilderu