Flutter w programowaniu mobilnym: co to jest, kluczowe pojęcia i jak działa

Autor: IT Sectr Opublikowano: 2026-07-09 Czas czytania: 11 min

Flutter to framework UI od Google do natywnych aplikacji wieloplatformowych. Według Flutter Docs (2025), Flutter jest używany w ponad 500 000 aplikacji w Google Play. Zrozumienie Widget, StatefulWidget, BuildContext i drzewa renderowania to podstawa programowania we Flutterze.

Najważniejsze

  • Widget — podstawowy blok konstrukcyjny. StatelessWidget (niezmienny) vs StatefulWidget (zmienny z setState()).
  • Trzy drzewa: Widget Tree (konfiguracja), Element Tree (elementy), RenderObject Tree (renderowanie).
  • BuildContext — dostęp do InheritedWidget: Theme, MediaQuery, Navigator. InheritedWidget — przekazywanie danych w dół.
  • Navigator — stos ekranów (Routes). Navigator 2.0 (Router) — deklaratywna nawigacja.
  • Hot Reload — wstrzykiwanie zmian w 1-2 sekundy. Zachowuje stan. Hot Restart — pełny restart.

Flutter: podstawy Widget, StatelessWidget i StatefulWidget

Widget — deklaratywny opis części UI. Wszystko we Flutterze jest Widgetem: od przycisku do samej aplikacji. Widget to konfiguracja (nie samo UI). StatelessWidget — niezmienny Widget. build() jest wywoływany raz. Nie ma stanu. Używany do statycznej treści. StatefulWidget — zmienny Widget. Ma obiekt State, który może się zmieniać. setState() — wyzwala przebudowę. State — zmienny obiekt powiązany z StatefulWidget. Zawiera dane, które mogą się zmieniać.

StatelessWidget vs StatefulWidget

StatelessWidget — build() jest wywoływany raz. Nadaje się do nagłówków, ikon, statycznych tekstów. StatefulWidget — build() jest wywoływany za każdym razem, gdy wywołano setState(). Nadaje się do formularzy, list ze zmianami, timerów. InheritedWidget — przekazywanie danych w dół bez jawnego przekazywania przez konstruktory. Theme, MediaQuery, Navigator — InheritedWidgets. BuildContext — pozycja Widgeta w drzewie. context.of<T>, context.watch<T>, context.select<T,R> — dostęp do InheritedWidget.

dart
// Przykład Flutter Widget: StatefulWidget z setState
class CounterWidget extends StatefulWidget {
  const CounterWidget({Key? key}) : super(key: key);

  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Counter')),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

Widget — konfiguracja. StatelessWidget — niezmienny. StatefulWidget — zmienny z setState(). IT Sectr zaleca zaczynanie od StatelessWidget i przechodzenie na StatefulWidget tylko gdy potrzebny jest stan.

Drzewa (Widget Tree, Element Tree, RenderObject Tree)

Flutter używa trzech drzew do wydajnego renderowania. Widget Tree — drzewo konfiguracji. Widgety są tworzone często (każdy build), lekkie. Element Tree — drzewo elementów. Jeden element na Widget (jeśli typ się nie zmienia). Element — most między Widgetem a RenderObject. RenderObject Tree — drzewo renderowania. Odpowiada za rozmiary, pozycje, rysowanie. RenderObject — ciężki, tworzony rzadko. Flutter porównuje Widget Tree i aktualizuje Element Tree, co wyzwala aktualizację RenderObject Tree.

Keys i Element Tree

Key — identyfikator Widgeta w Element Tree. ValueKey, ObjectKey, UniqueKey, PageStorageKey. Keys pozwalają Flutterowi dopasowywać stare i nowe Widgety podczas przebudowy. Bez Keys Flutter dopasowuje według typu Widgeta i pozycji. GlobalKey — dostęp do State z innego Widgeta. Używane do: złożonych formularzy, animacji, dostępu do State w testach. IT Sectr zaleca używanie Keys dla list (List.generate) i unikanie GlobalKey, chyba że to konieczne.

Expanded — Widget wypełniający dostępne miejsce w Row/Column/Flex. Flexible — nie wymusza wypełnienia (może być mniejszy). MediaQuery — InheritedWidget z informacjami o urządzeniu: rozmiar ekranu, orientacja, platforma, współczynnik skali tekstu. Theme/ThemeData — scentralizowany motyw. Theme.of(context) — dostęp. MaterialApp — główny Widget do konfiguracji routingu, motywów, ustawień regionalnych. Scaffold — podstawowy układ z AppBar, Drawer, BottomNavigationBar. AppBar — górny panel.

Navigator — stos tras (Routes). Navigator.push — otwórz ekran (zwraca Future). Navigator.pop — zamknij (z wynikiem). MaterialPageRoute — animowane przejście (przesunięcie z prawej). Named Routes — identyfikatory tekstowe. onGenerateRoute — scentralizowany handler. Navigator 2.0 (Router + RouteInformationParser + RouterDelegate) — deklaratywna nawigacja dla web, deep linking i złożonych scenariuszy.

Navigator 2.0 — deklaratywna nawigacja. Router — centralny Widget. RouteInformationParser — parsowanie URL. RouterDelegate — zarządzanie stosem. GoRouter (pakiet) — uproszczona otoczka nad Navigator 2.0. Obsługuje: nazwane trasy, parametry, przekierowania, deep linking. IT Sectr zaleca GoRouter dla większości projektów i Navigator 2.0 tylko dla złożonych scenariuszy (web, desktop).

Asynchroniczność (FutureBuilder, StreamBuilder)

FutureBuilder — Widget budujący UI w oparciu o Future. connectionState: none, waiting, active, done. Używane do: żądań HTTP, odczytu BD, timerów. StreamBuilder — Widget dla Stream (nieskończony strumień danych). snapshot.data, snapshot.hasError, snapshot.hasData. Używane do: WebSocket, Firebase, aktualizacji lokalizacji. Oba Widgety przebudowują się po otrzymaniu nowych danych.

Zarządzanie stanem

Provider — prosty DI + zarządzanie stanem. ChangeNotifierProvider, MultiProvider. Riverpod — nowoczesna zamiana Providera: bezpieczny w kompilacji, niezależny od BuildContext. Bloc — architektura Event-Driven: Cubit (proste zdarzenia) vs Bloc (złożone). GetX — lekkie zarządzanie stanem + DI + routing. setState — najprostsze, dla lokalnego stanu. IT Sectr zaleca Riverpod dla nowych projektów i Provider dla istniejących.

Motywy i adaptacja (MediaQuery, ThemeData)

MediaQuery — rozmiar ekranu, orientacja, platforma, textScaleFactor. MediaQuery.of(context).size.width. ThemeData — motyw aplikacji: kolory, czcionki, kształty. Theme.of(context).textTheme.bodyLarge. Hot Reload — wstrzykiwanie kodu do działającej aplikacji. Zachowuje stan. Nie obsługuje: zmiany main(), zmiennych globalnych, pól statycznych. Hot Restart — pełny restart aplikacji (utrata stanu). Hot Reload — główna zaleta Fluttera dla programistów.

Typ Widgeta Opis Przykłady
StatelessWidgetNiezmienny, build razText, Icon, Padding, Center
StatefulWidgetZmienny, setState przebudowaTextField, Checkbox, AnimationController
InheritedWidgetPrzekazywanie danych w dółTheme, MediaQuery, Navigator
ProxyWidgetOtoczka dla innych WidgetówParentDataWidget (Positioned, Expanded)
RenderObjectWidgetTworzy RenderObjectColumn, Row, Stack (niestandardowe)

StatelessWidget — do treści statycznych. StatefulWidget — do treści dynamicznych. InheritedWidget — do DI. IT Sectr zaleca domyślnie StatelessWidget i StatefulWidget tylko w razie potrzeby.

Responsywny układ

LayoutBuilder — adaptacja do wymiarów rodzica. OrientationBuilder — adaptacja do orientacji. Expanded vs Flexible — dystrybucja miejsca w Row/Column. MediaQuery — punkty graniczne dla tabletów i desktopów. SafeArea — marginesy od elementów systemowych (notch, pasek stanu). AspectRatio — zachowanie proporcji. IT Sectr zaleca LayoutBuilder dla adaptacyjnych układów i OrientationBuilder dla orientacji poziomej.

Testowanie (Widget, Integration, Unit)

Testy jednostkowe — testowanie logiki biznesowej, repozytoriów, modeli. dart test — uruchomienie. Testy Widgetów — testowanie widgetów w izolacji. WidgetTester — pumpWidget, tap, enterText. Testy integracyjne — pełne scenariusze na rzeczywistym urządzeniu/emulatorze. Mockito — mockowanie zależności. Golden testy — porównywanie zrzutów ekranu (pliki golden). IT Sectr zaleca testy Widgetów dla każdego ekranu i testy jednostkowe dla logiki biznesowej.

dart
void main() {
  testWidgets('Counter increments on tap', (tester) async {
    await tester.pumpWidget(const MaterialApp(home: CounterWidget()));

    expect(find.text('0'), findsOneWidget);

    await tester.tap(find.byType(FloatingActionButton));
    await tester.pump();

    expect(find.text('1'), findsOneWidget);
  });
}

Animacje (Niejawne, Jawne, Hero)

Animacje niejawne — AnimatedContainer, AnimatedOpacity, AnimatedPadding, TweenAnimationBuilder. Zmiany właściwości są automatycznie animowane. Animacje jawne — AnimationController z Tween. forward() / reverse(). Animacja Hero — Widget Hero z tagiem — animacja przejścia między ekranami. Animacja stopniowana — łańcuch animacji z Interval. Lottie — integracja animacji After Effects. Rive — interaktywne animacje (state machine). IT Sectr zaleca AnimatedContainer w 80% przypadków i AnimationController dla złożonych scenariuszy.

dart
class AnimatedBox extends StatefulWidget {
  @override
  State<AnimatedBox> createState() => _AnimatedBoxState();
}

class _AnimatedBoxState extends State<AnimatedBox> {
  bool _expanded = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => setState(() => _expanded = !_expanded),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        width: _expanded ? 200 : 100,
        height: _expanded ? 200 : 100,
        color: _expanded ? Colors.blue : Colors.red,
        child: const Center(child: Text('Tap me')),
      ),
    );
  }
}

Sieć (http, dio, graphql)

http — prosty klient HTTP (get, post, put, delete). dio — zaawansowany klient z interceptorem, timeoutami, ponawianiem, logowaniem. graphql_flutter — klient GraphQL dla Fluttera. json_serializable — generowanie fromJson/toJson przez adnotacje. Retrofit Dart — type-safe klient HTTP jak Retrofit. WebSocket — przez web_socket_channel. Firebase — Cloud Firestore, Realtime Database, Cloud Functions. IT Sectr zaleca dio dla REST API i graphql_flutter dla GraphQL.

Flutter DevTools — zestaw narzędzi: Inspector (drzewo widgetów), Timeline (wydajność), Memory, Network, Logging. Profile mode — profilowanie bez debugowania. Performance overlay — FPS, czasy budowania. Flame chart — śledzenie wykresu płomieni. DevTools — niezbędne narzędzie do optymalizacji aplikacji Flutter w produkcji.

Flutter Web — kompilacja Fluttera do WASM (WebAssembly). CanvasKit (Skia) vs HTML renderer. CanvasKit — pixel-perfect, ale cięższy. HTML renderer — lekki, ale z ograniczeniami. WASM (Flutter 3.22+) — natywna wydajność. Responsywna adaptacja przez LayoutBuilder i MediaQuery. IT Sectr zaleca CanvasKit dla desktopowych aplikacji webowych i HTML renderer dla stron treściowych.

Często zadawane pytania

Jaka jest różnica między StatelessWidget a StatefulWidget?

StatelessWidget — niezmienny, build raz. StatefulWidget — ze zmiennym Stanem i setState().

Czym są Widget Tree, Element Tree i RenderObject Tree?

Widget Tree — konfiguracja. Element Tree — most. RenderObject Tree — renderowanie (rozmiary, rysowanie).

Czym są BuildContext i InheritedWidget?

BuildContext — pozycja Widgeta w drzewie. InheritedWidget — przekazywanie danych w dół (Theme, MediaQuery).

Jak działają Navigator i Route we Flutterze?

Navigator — stos ekranów. push() → pop(). Named Routes — nazwy tekstowe. Navigator 2.0 — deklaratywny.

Jak działa Hot Reload we Flutterze?

Hot Reload — wstrzykiwanie kodu w 1-2 sekundy, zachowanie stanu. Hot Restart — pełny restart.

Podsumowanie

  • Widget — wszystko jest Widgetem. StatelessWidget vs StatefulWidget — podstawowa dychotomia.
  • Trzy drzewa: Widget → Element → RenderObject. Widget — konfiguracja, RenderObject — renderowanie.
  • BuildContext + InheritedWidget — dostęp do Theme, MediaQuery, Navigator bez jawnego przekazywania.
  • Navigator — stos ekranów. Navigator 2.0 — deklaratywna nawigacja dla web i deep linków.
  • FutureBuilder — dla Future. StreamBuilder — dla Stream (Firebase, WebSocket).
  • MaterialApp + Scaffold — szkielet aplikacji. ThemeData — scentralizowany motyw.
  • Hot Reload — zabójcza funkcja Fluttera. Aktualizacja kodu w sekundach z zachowaniem stanu.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt