State: vad är det, tillståndshantering och funktionsprincip

Författare: IT Sectr Publicerad: 2026-07-01 Lästid: 9 min

State — det centrala objektet för datahantering i Flutter, associerat med StatefulWidget och ansvarigt för att lagra föränderlig information och bygga gränssnittet. Enligt officiella Flutter-dokumentationen (Flutter.dev, 2026) finns State under hela widgetens livscykel och överlever dess ombyggnationer, vilket säkerställer datakonsistens mellan UI-uppdateringar. Till skillnad från själva widgeten kan State ändra sina fält och initiera ombyggnation genom att anropa setState.

Huvudpunkter

  • State — objekt som lagrar StatefulWidgets föränderliga data och hanterar dess ombyggnation via setState
  • Livscykel — State går igenom initState, didChangeDependencies, build, didUpdateWidget och dispose, varje steg med ett tydligt syfte
  • mounted — flagga som indikerar att State fortfarande är i widgetträdet och säkert kan anropa setState
  • widget — referens till den associerade StatefulWidget, tillgänglig via State-egenskapen för att läsa förälderns parametrar
  • Isolering — State är isolerat från andra State; för datautbyte används InheritedWidget eller externa verktyg för tillståndshantering

Vad är State i Flutter?

State — är ett objekt i Flutter-arkitekturen som lagrar StatefulWidgets föränderliga data och bestämmer hur dessa data visas i gränssnittet. Varje StatefulWidget skapar vid inbäddning i trädet exakt ett State-objekt genom metoden createState. State existerar oberoende av widgeten: om föräldern bygger om StatefulWidget med nya parametrar, förblir State densamma och tar emot den uppdaterade widgeten via egenskapen widget.

Enligt Flutter Architectural Overview (Google, 2026) är separationen av Widget och State ett medvetet arkitektoniskt beslut som gör det möjligt för ramverket att återanvända trädelement. Widgeten (lätt beskrivning) kan skapas och förstöras flera gånger, men State (tungt objekt med data) finns kvar i minnet så länge elementet är i trädet. Detta förhindrar dataförlust vid frekventa ombyggnationer av föräldrawidgets.

State implementerar gränssnittet StatefulWidget via en generik: class _MyState extends State<MyWidget>. Generiken binder State till en specifik StatefulWidget-typ och ger typsäker åtkomst till dess fält via egenskapen widget.

Var lagras State?

State-objektet lagras i StatefulElement — det mellanliggande lagret mellan Widget och RenderObject. StatefulElement skapar State via createState, behåller referensen till det och överför State som ägare. Elementet förstörs endast när widgeten tas bort från trädet — fram till dess lever State i minnet.

States livscykel

Livscykeln för State är deterministisk och består av en strikt sekvens av anrop. Att förstå denna sekvens är grunden för korrekt arbete med resurser och förhindrande av minnesläckor.

initState — initiering

initState anropas först när State skapas. I denna metod initieras kontroller, prenumerationer på dataströmmar, timers och initiala värden för fält. Att anropa super.initState() på första raden är obligatoriskt. I initState-fasen är widgetträdet ännu inte fullt monterat, så metoder som MediaQuery.of(context) kan fungera felaktigt.

didChangeDependencies

didChangeDependencies anropas efter initState och vid varje ändring av InheritedWidget-beroenden. Just här, inte i initState, bör MediaQuery.of(context) eller Theme.of(context) anropas, eftersom trädet vid denna tidpunkt redan är monterat. Denna metod anropas också om widgeten flyttas till en annan kontext där InheritedWidget ger andra värden.

build — bygga UI

build — States huvudmetod som returnerar widgetträdet. Anropas efter initState, efter didChangeDependencies och efter varje setState. Metoden build bör inte ha sidoeffekter — den beskriver bara gränssnittet baserat på aktuella värden för States fält.

didUpdateWidget

didUpdateWidget anropas när föräldern bygger om StatefulWidget med nya parametrar. State får tillgång till den gamla widgeten via oldWidget och kan jämföra den med den nya. Om parametrarna har ändrats kan tillståndet uppdateras, ny data laddas eller animeringen startas om.

dispose — frigöra resurser

dispose — den avslutande metoden där alla resurser frigörs: kontroller, prenumerationer, timers. Efter dispose markeras State som död: mounted returnerar false, ett anrop av setState kastar ett undantag. Att anropa super.dispose() på metodens sista rad är obligatoriskt.

MetodNär anropasObligatorisk super
initStateNär State skapasJa, på första raden
didChangeDependenciesEfter initState och vid InheritedWidget-förändringJa
buildEfter initState, didChangeDependencies, setStateNej
didUpdateWidgetVid ny widget från förälderJa
setStateVid anrop av utvecklarenNej
disposeVid borttagning från trädetJa, på sista raden

Hur fungerar State?

Mekanismen för State bygger på tre nyckelprinciper: association med Element, reaktivitet via setState och åtkomst till föräldern via egenskapen widget. När Flutter bygger elementträdet och stöter på StatefulElement, anropar det createState för den associerade widgeten. Det skapade State lagras i elementet och finns kvar tills elementet tas bort.

När setState anropas markerar State sig själv som ”irty” och schemalägger ombyggnation för nästa bildruta. Viktigt: setState anropar inte build omedelbart — det registrerar bara behovet av ombyggnation. Flutter samlar alla dirty-element i den aktuella bildrutan och bygger om dem i batch, vilket optimerar prestandan. Efter build-anropet återgår State till ”clean”-tillstånd.

Egenskapen widget låter State läsa parametrarna som skickats till StatefulWidget-konstruktorn. Eftersom StatefulWidget är oföränderlig (som StatelessWidget) ändras dess fält inte — när parametrar ändras skapar föräldern en ny widget och State tar emot den via didUpdateWidget. Detta garanterar att State alltid arbetar med aktuell data från föräldern.

Kodexempel i Dart

Grundläggande exempel på State med ett fält som ändras av en timer. Demonstrerar initState, setState och dispose:

dart
class _TimerWidgetState extends State<TimerWidget> {
  int _seconds = 0;
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(
      const Duration(seconds: 1),
      (_) => setState(() => _seconds++),
    );
  }

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Text('$_seconds sekunder har gått');
  }
}

Exempel på användning av egenskapen widget för åtkomst till förälderns parametrar och reaktion på deras förändringar via didUpdateWidget:

dart
class _GreetingState extends State<GreetingWidget> {
  String _displayName = '';

  @override
  void initState() {
    super.initState();
    _displayName = _formatName(widget.name);
  }

  @override
  void didUpdateWidget(GreetingWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.name != oldWidget.name) {
      setState(() {
        _displayName = _formatName(widget.name);
      });
    }
  }

  String _formatName(String name) => name.trim().isEmpty ? 'Guest' : name;

  @override
  Widget build(BuildContext context) {
    return Text('Hej, $_displayName!');
  }
}

I det andra exemplet övervakar State ändringen av ingångsparametern name och omformaterar visningen endast vid verklig ändring. Utan kontrollen widget.name != oldWidget.name skulle metoden anropas vid varje ombyggnation av föräldern, även om namnet inte ändrades — onödigt arbete för ramverket.

State vs StatefulWidget

State och StatefulWidget är två olika klasser i Flutter-arkitekturen med olika roller. StatefulWidget är ett lätt oföränderligt omslag som beskriver widgetens konfiguration och skapar State. State är ett tungt objekt som lagrar föränderlig data, hanterar prenumerationer och bygger UI. Denna separation gör att Flutter kan förstöra och skapa widgets utan att förlora tillstånd.

Alla fält i StatefulWidget måste vara final och anges i konstruktorn — de ändras inte efter skapande. State däremot kan ändra sina fält när som helst, men alla ändringar måste föregås av ett anrop till setState, så att Flutter får reda på behovet av ombyggnation. Detta är den viktigaste skillnaden: StatefulWidget är ”vad som ska visas”, State — ”hur det ska visas och vilken data som ska användas”.

Enligt Flutter source code analysis (Flutter SDK, 2026) innehåller StatefulWidget bara ett obligatoriskt fält — createState, medan State har tillgång till BuildContext, kan prenumerera på strömmar, hantera animationer och kontroller. Det rekommenderas att hålla StatefulWidget så enkel som möjligt och flytta all logik till State.

Varför kan StatefulWidget inte vara State?

Separationen av Widget och State är ett arkitektoniskt beslut som säkerställer konfigurationens oföränderlighet. Om StatefulWidget själv lagrade tillståndet skulle tillståndet gå förlorat vid varje ombyggnation av föräldern. Genom att flytta tillståndet till ett separat objekt garanterar Flutter att data överlever ombyggnationer och att widgets förblir lätta och jämförbara.

Tillståndshantering mellan widgets

State-objektet är isolerat — det har ingen direkt åtkomst till andra widgets State. För datautbyte mellan widgets används InheritedWidget eller externa verktyg för tillståndshantering: Provider, Riverpod, Bloc, Redux. Varje metod löser problemet på sitt sätt: InheritedWidget arbetar via widgetträdet, Provider — via en DI-behållare, Bloc — via händelseströmmar.

Valet av verktyg beror på projektets omfattning. För en liten applikation räcker InheritedWidget och lokalt State. För medelstora och stora projekt rekommenderas Riverpod eller Bloc — de ger testbarhet, förutsägbarhet och separation av logik från UI. State används då endast för widgetens lokala data (fokus, rullning, animering).

Enligt Flutter Community Survey 2025 (Flutter Foundation, december 2025) är Riverpod den mest populära lösningen för tillståndshantering i nya projekt (38%), följt av Bloc (31%) och Provider (22%). Alla tre verktygen är kompatibla med State och kräver inte att man frångår den standardmässiga livscykeln.

Lokalt vs globalt tillstånd

  • Lokalt tillstånd — i State för en specifik widget (rullposition, fokusstatus)
  • Globalt tillstånd — i extern lagring (användardata, inställningar, cache)
  • Regel: om data endast används av en widget — lagra i State
  • Om data används av 2+ widgets — flytta till Riverpod/Bloc/Provider

Vanliga misstag

Första misstaget — glömma att kontrollera mounted före setState i en asynkron återuppringning. När widgeten har tagits bort från trädet (t.ex. användaren lämnade skärmen), men den asynkrona operationen (HTTP-begäran) fortfarande körs, är State redan död efter dess slutförande. Att anropa setState i ett dött State kastar ett undantag. Kontrollen if (mounted) setState(...) löser problemet.

Andra misstaget — initiering av InheritedWidget-beroenden i initState istället för didChangeDependencies. I initState är kontexten ännu inte monterad, så MediaQuery.of(context) kommer att kasta ett undantag. Alla InheritedWidget-beroenden bör konfigureras i didChangeDependencies eller i build.

Tredje misstaget — mutering av fält utan att anropa setState. Om utvecklaren ändrar ett State-fält utan setState, får Flutter inte reda på ändringen och UI uppdateras inte. Till exempel: _list.add(item) utan efterföljande setState((){}) kommer att ändra listan, men skärmen förblir densamma.

Kontroll av mounted före setState

Säkerhetsmönster för asynkrona operationer i State:

dart
Future<void> _fetchData() async {
  final data = await ApiService.fetch();
  if (mounted) {
    setState(() => _data = data);
  }
}

Kontroll av mounted garanterar att setState endast anropas för ett levande State, vilket förhindrar undantaget ”setState called after dispose”.

Vanliga frågor

Vad skiljer State från StatefulWidget?

StatefulWidget är widgetens oföränderliga konfiguration, medan State är ett föränderligt objekt som lagrar data och hanterar livscykeln. Widgeten kan återskapas, State — inte. StatefulWidget skapar State via createState.

Hur många State-objekt skapas för en StatefulWidget?

Exakt ett. Metoden createState anropas en gång vid första inbäddningen av StatefulWidget i trädet. Även om föräldern byggs om flera gånger förblir State-objektet detsamma, tills widgetens typ eller Key ändras.

Vad är mounted i State?

mounted är en boolesk flagga som visar om State finns i widgetträdet. Efter anrop av dispose blir mounted false. Används för kontroll före setState i asynkrona återuppringningar för att undvika undantag.

Kan State användas utan StatefulWidget?

Nej. State är alltid bundet till en specifik StatefulWidget via en generik: State<T extends StatefulWidget>. Att skapa State direkt, utan association med en widget, är arkitektoniskt omöjligt.

Vad händer om setState anropas i dispose?

Ett undantag kastas: ”setState called after dispose”. Efter anrop av dispose anses State vara dödt och alla försök att bygga om UI via setState är förbjudna. Lösning — kontrollera mounted före varje setState.

Sammanfattning

  • State — StatefulWidgets datahanteringsobjekt, lagrar föränderliga fält och initierar UI-ombyggnation via setState
  • Livscykel omfattar de obligatoriska metoderna initState, didChangeDependencies, build, didUpdateWidget och dispose, var och en med sitt syfte
  • mounted — kritisk säkerhetsflagga som förhindrar anrop av setState efter borttagning av widgeten från trädet
  • widget — States egenskap för åtkomst till parametrar för den associerade StatefulWidget, uppdaterad via didUpdateWidget
  • Isolering — State har ingen åtkomst till andra State; interaktion mellan widgets sker via InheritedWidget eller externa verktyg
  • setState — anropar inte build omedelbart, markerar bara State som dirty för ombyggnation i nästa bildruta
  • Regel — använd State för lokal widgetdata; flytta globalt tillstånd till externa lager (Riverpod, Bloc)

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också