Flutter SK/CZ – #1.2 – WebView Controller – Completer, Future Builder, Await – Async

Úvod

Vitajte na stránke Himdeve development, kde pre Vás pripravujeme tie najlepšie tutoriály, ktoré Vám uľahčia a zefektívnia vývoj mobilných aplikácií.

Cieľ

  1. V tomto druhom diele našej Flutter SK/CZ série tutoriálov pridáme controller pre naše WebView aby sme ho následne vedeli plne ovládať, ako napríklad získavať aktuálnu url adresu, ísť v histórii dopredu, dozadu, refreshovať stránku, vymazať cache a podobne. V našom prípade zobrazíme aktuálnu url adresu.
  2. Okrem toho pridáme topBar a floating action button do aplikácie.
  3. Naučíme sa rozdiel medzi Stateless Widgetom a Stateful Widgetom
  4. A takisto základné info o koncepte Future, FutureBuilder, Completer a Async – Await mechanizme vo Flutteri.

Postup

Najskôr otvoríme našu existujúcu aplikáciu z predchádzajúceho tutoriálu a otvoríme súbor shop_page.dart.

Ako prvý krok pridáme do nášho ShopPage widgetu Scaffold widget. Scaffold widget poskytuje framework, ktorý implementuje štruktúru základného material dizajn vizuálneho layoutu pre Flutter aplikáciu. Ponúka API pre zobrazenie appBars, drawers, snack bars, floating buttons, bottom sheet a mnoho ďalších komponentov a dá sa tu takisto nastavovať farba pozadia, pridávať navigačné bary a podobne.

V našom prípade pridáme do ShopPage stránky AppBar, kde nastavíme názov widgetu a floatingActionButton, ktorým budeme vykonávať určité akcie počas behu aplikácie. Scaffold widget má takisto atribút body, v ktorom sa vykresľuje hierarchia ďalších widgetov. V našom prípade WebView.

Copy to Clipboard

Stateless Widget vs Stateful Widget

Zmeníme Stateless Widget na Stateful Widget, čiže ShopPage bude dediť od StatefulWidgetu. Konštruktor zostáva takmer rovnaký až na to, že zrušíme const parameter.

Rozdiel medzi Stateless Widgetom a Stateful Widgetom

Stateless Widget

Stateless widgety nevyžadujú mutable state, čo znamená, že sú nemenné = immutable.

Čiže nemôžu meniť svoj stav počas behu aplikácie. To znamená, že widgety, ktoré sú vykreslené v tejto hierarchii widgetov pod Stateless Widgetom v metóde build nemôžu byť prekreslené počas behu aplikácie.

Metóda build je zavolaná len raz počas behu aplikácie. Metóda build je zodpovedná za vykreslovanie widgetov na obrazovku. Keby sme chceli znovu vykresliť Stateless Widget, tak by sme museli vytvoriť jeho novú inštanciu.

Stateful Widget

Stateful Widgety majú mutable state, čiže sú menné a môžu byť vykreslené na obrazovku viackrát počas jedného behu aplikácie.

Stateful WidgetcreateState metódu, ktorou vrátime inštanciu stavu widgetu, v našom prípade inštanciu privátne triedy _ShopPageState. Táto trieda dedí zo State objektu, ktorý má metódu build a táto metóda môže byť zavolaná niekoľko krát počas behu aplikácie aby prekreslila obrazovku.

shop_page.dart

Copy to Clipboard

Najjednoduchší spôsob ako prekresliť obrazovku je použitím metódy setState, ktorá zavolá build metódu a tá teda následne znovu vykreslí všetky widgety vo svojej hierarchii widgetov.

SetState metóda

Aby sme si vyskúšali ako funguje setState metóda v praxi, tak si vytvoríme privátnu metódu _buildChangeTitleBtn , ktorá nám teda vráti FloatingActionButton, kde na jeho kliknutie zmeníme title pre tento screen z ‘Himdeve Shop’ na ‘Himdeve Development Tutorial’.

Copy to Clipboard

WebView Controller a Future

Bohuzial WebView widget moc nefunguje na setState metódu, čiže keby sme chceli napríklad zmeniť url adresu WebView z https://himdeve.eu na https://himdeve.com, tak musím použiť WebView Controller, ktorý má na to špeciálnu metódu: loadUrl(‘your_new_url’).

Webview je widget, ktorý musí byť vykreslený na obrazovku a takisto musí inicializovať svoj stav. Tento proces je asynchrónny a trvá určitú krátku dobu. To však znamená, že keby sme chceli teraz priamo pristupovať ku WebView Controlleru, tak nemusí byť ešte pripravený. Pripravený bude až v určitej budúcnosti. A preto použijeme triedu Completer, ktorá nám umožní spracovať Future objekty (budúcnosť) a následne ich dokončiť s ich hodnotou, prípadne errorom. 

Completer a Future Builder

Čiže v našom prípadne Completer objekt zakapsuluje WebView Controller a my môžeme následne kontrolovať, či už je WebView Controller pripravený (validný) pomocou volanie metódy _controller.isCompleted alebo použiť triedu FutureBuilder, čo je vlastne widget, ktorý sa builduje na základe najnovšej snímky (snapshotu) interakcie s budúcnosťou (Future). To v našom prípade znamená, že FutureBuilder nám umožní vytvoriť nové UI widgety ako teda napríklad náš FloatingActionButton až potom ako máme pripravený náš validný WebView Controller.

Čiže zadefinujeme WebView Controller zakapsulovaný do Completeru.

Copy to Clipboard

Vo WebView objekte nastavíme nový atribút onWebViewCreated, ktorý nám vracia objekt WebView Controller, keď je pripravený a tento objekt nastavime namiesto nášho placeholdera v Completeri.

Copy to Clipboard

Následne budeme chcieť vytvoriť metódu, ktorá nám vráti FloatingActionButton, ktorý bude zobrazovať aktuálnu url adresu našej stránky z WebView. Nazveme ju _buildShowUrlBtn. A teda metódu _buildChangeTitleBtn nahradíme metódou _buildShowUrlBtn aj v Scaffold widgete. A táto metóda vracia FutureBuilder widget WebViewControlleru, kde Future tvori info o tom, či je WebView Controller validný. A validný je teda vtedy, keď Completer má dáta (controller.hasData). Vtedy vrátime FloatinActionButton widget, ináč vrátime prázdny Container widget.

Copy to Clipboard

 

Získanie url adresy

Interakciu stlačenia FloatingActionButtonu zachytíme pomocou atribútu onPressed a následne z WebView Controllera získame aktuálnu url adresu zobrazenú vo WebView pomocou príkazu: controller.data.currentUrl().

Copy to Clipboard

Async – Await mechanizmus

Čo je tu dôležité si uvedomiť je, že WebView Controller v našom completeri je Future objekt, čo znamená, že ak chceme jeho hodnotu získať v prítomnosti, tak musíme použiť async – away mechanizmus.

Away

Týmto príkazom sa pozastaví bežiaci kód a čaká sa kým sa vyrieši budúcnosť (Future) – čiže v našom prípade dokým sa získa hodnota aktuálnej url adresy z WebView Controllera a následne pokračuje na ďalší riadok.

Async

Pri použití await vo funkcii, tejto funkcii hrozí zablokovanie hlavného vlákna (main threadu) a preto musí byť označená príkazom async aby sme ju spravili asynchrónnou. 

Čo je dôležité si uvedomiť, že onPressed atribút, čo je vlastné callback metóda FloatingActionButtonu, doteraz vracia void, čiže kvazi nevracia nič. Avšak teraz tým, že sme ju označili príkazom async, tak už musí vracať budúcnosť, v tomto prípade Future< Void >. V tomto príklade na tom nezáleží, keďže onPressed v podstate nič v skutočnosti nevracia. Ale keby sme mali funkciu, ktorá vracia napríklad Integer hodnotu. Tak akonáhle použijeme async prikaz, tak musime definovať návratovú hodnotu funkcie z Integer na Future< Integer>.

Zobrazenie url adresy

Na zobrazenie url adresy použijeme SnackBar widget, kde využijeme jeho atribút Content, do ktorého vložíme Text widget s aktuálnou hodnotou WebView url adresy a nastavíme štýl pre tento Text widget, kde mu zväčšíme veľkosť písma (fontsize).

Scaffold.of(context) znamená, že vrátime Scaffold z najbližšieho predka Scaffoldu v tejto hierarchii widgetov, čiže v našom prípade ten Scaffold, ktorý sme vytvorili pre túto triedu _ShopPageState. A následne v ňom zobrazíme daný SnackBar pomocou nasledovnej funkcie Scaffold.of(context).showSnackBar.

Copy to Clipboard

Záver

A tým je naša druhá časť tejto prvej série Flutter SK/CZ Tutoriálov ukončená a kompletný zdrojový kód môžete samozrejme nájsť na githube.