StatefulWidget: ano ito, lifecycle at prinsipyo ng paggawa

May-akda: IT Sectr Nai-publish: 2026-07-01 Oras ng pagbabasa: 9 min

StatefulWidget — isang Flutter widget na may nababagong estado, na nagpapahintulot sa UI na tumugon sa mga aksyon ng user, mga asynchronous na kaganapan at mga daloy ng data. Ayon sa opisyal na dokumentasyon ng Flutter (Flutter.dev, 2026), ang StatefulWidget ay ginagamit para sa lahat ng interactive na elemento ng application: mga form ng input, mga animation, mga checkbox, mga switch at mga screen na naglo-load ng data mula sa network. Hindi tulad ng StatelessWidget, lumilikha ito ng isang hiwalay na State object na pinapanatili sa buong lifecycle at maaaring muling itayo nang hindi muling nililikha ang widget mismo.

Mga Pangunahing Punto

  • StatefulWidget — widget na maaaring magbago ng estado nito habang tumatakbo, na nagti-trigger ng muling pagtatayo ng UI sa pamamagitan ng setState
  • Lifecycle — StatefulWidget ay dumadaan sa mga yugto ng createState, initState, didChangeDependencies, build, didUpdateWidget, dispose
  • State object — isang hiwalay na bagay na nag-iimbak ng estado at umiiral nang independyente sa widget sa buong buhay nito
  • setState — ang tanging lehitimong paraan upang abisuhan ang Flutter tungkol sa pangangailangan na muling itayo ang widget pagkatapos ng pagbabago ng data
  • Pagganap — ang labis na paggamit ng StatefulWidget ay nagpapataas ng konsumo ng memorya at oras ng rendering

Ano ang StatefulWidget?

StatefulWidget — ay isang Flutter class na maaaring magbago ng estado nito bilang tugon sa mga aksyon ng user, mga kaganapan ng system o mga asynchronous na operasyon. Hindi tulad ng StatelessWidget, ang StatefulWidget ay hindi direktang ipinapakita — lumilikha ito ng isang State object na responsable sa rendering. Ang paghahati sa dalawang klase (Widget at State) ay nagpapahintulot sa Flutter na muling itayo ang UI nang hindi muling nililikha ang widget mismo, na nagbibigay ng malaking bentahe sa pagganap sa mga madalas na pag-update.

Ang arkitektura ng StatefulWidget ay sumusunod sa pattern na «paghihiwalay ng nababago at hindi nababago»: ang widget mismo ay nananatiling hindi nababago (tulad ng StatelessWidget), at ang lahat ng nababagong estado ay naka-imbak sa isang hiwalay na State object. Ito ay nagpapahintulot sa Flutter na muling gamitin ang mga widget sa pamamagitan ng paghahambing sa kanila ayon sa uri at Key, habang pinapanatili ang kasalukuyang estado sa pagitan ng mga muling pagtatayo.

Ayon sa Google (Flutter Architectural Overview, 2026), ang StatefulWidget ay optimal para sa mga senaryo kung saan ang estado ay nagbabago nang higit sa isang beses sa buhay ng widget: mga text field, animation, timer, data stream, asynchronous na pag-load. Para sa isang beses na initialization, sapat na ang StatelessWidget.

Kailan Kailangan ang StatefulWidget

StatefulWidget ay sapilitan kapag ang widget ay dapat tumugon sa mga panlabas na kaganapan: pagpindot ng button, pagkumpleto ng HTTP request, pag-update ng data mula sa database, subscription sa WebSocket. Ito rin ay kinakailangan para sa mga widget na may animation, mga text field na may controllers at mga component na namamahala ng focus. Kung ang widget ay nagpapakita lamang ng data at hindi lumilikha ng mga kaganapan — gamitin ang StatelessWidget.

Panloob na Istraktura

Ang StatefulWidget ay binubuo ng dalawang klase: ang StatefulWidget mismo (magaan, hindi nababago) at State (mabigat, nababago). Ang framework ay lumilikha ng State sa pamamagitan ng createState() method, na tinatawag nang isang beses kapag inilagay sa tree. Ang State ay tumatanggap ng reference sa widget sa pamamagitan ng widget property at maaaring ma-access ang mga field nito anumang oras sa lifecycle.

Lifecycle ng StatefulWidget

Lifecycle ng StatefulWidget ay binubuo ng anim na pangunahing yugto, bawat isa ay nagbibigay ng isang overridable na method para sa pagsasagawa ng mga tiyak na gawain. Ang pag-unawa sa mga yugtong ito ay kritikal para sa tamang pagtatrabaho sa mga resource at pag-iwas sa memory leaks.

createState

createState — ang unang method ng lifecycle, na tinatawag kapag ang StatefulWidget ay inilagay sa tree. Dapat itong magbalik ng bagong instance ng State na nauugnay sa widget na ito. Ang method na ito ay tinatawag nang eksaktong isang beses sa buong buhay ng elemento. Mahalaga na huwag magsagawa ng mabibigat na operasyon dito — ang createState ay dapat na gaan hangga’t maaari.

initState

initState — ay tinatawag kaagad pagkatapos ng paglikha ng State, bago ang unang pagtatayo ng UI. Dito isinasagawa ang: initialization ng mga controller (TextEditingController, AnimationController), subscription sa mga data stream (StreamSubscription), pag-setup ng mga timer at paunang initialization ng mga field. Ayon sa Flutter docs (Flutter.dev, 2026), sa initState ay hindi maaaring tumawag ng BuildContext.of() — ang tree ay hindi pa ganap na naka-mount.

didChangeDependencies

didChangeDependencies — ay tinatawag pagkatapos ng initState at sa bawat oras na nagbabago ang mga dependency ng InheritedWidget. Ito ang tamang lugar para tumawag ng MediaQuery.of(context) o mag-subscribe sa Theme — mga value na maaaring magbago habang tumatakbo ang application. Kung ang widget ay gumagamit ng InheritedWidget, ang initialization logic ay dapat na dito, hindi sa initState.

build at didUpdateWidget

build — ang pangunahing method na nagbabalik ng widget tree. Tinatawag pagkatapos ng initState, pagkatapos ng didChangeDependencies at pagkatapos ng bawat setState. didUpdateWidget ay tinatawag kapag ang parent ay muling nagtatayo at nagpapasa ng StatefulWidget na may mga bagong parameter. Dito maaari mong ihambing ang luma at bagong mga field ng widget at, kung kinakailangan, i-update ang estado.

dispose

dispose — ang huling yugto ng lifecycle. Dito pinapalaya ang lahat ng resource: pag-unsubscribe mula sa mga stream, pagtanggal ng mga controller, pagkansela ng mga timer. Ang hindi pagtawag ng dispose ay humahantong sa memory leaks. Pagkatapos ng dispose, ang State ay itinuturing na patay — ang pagtawag ng setState sa loob nito ay nagtatapon ng exception.

Paano gumagana ang StatefulWidget?

Ang mekanismo ng paggawa ng StatefulWidget ay batay sa koordinadong gawain ng tatlong entity: Widget (magaan na paglalarawan), Element (intermediate layer) at State (imbakan ng data). Kapag nakatagpo ang Flutter ng StatefulWidget sa paglalarawan, lumilikha ito ng StatefulElement na tumatawag ng createState at nag-iimbak ng reference sa State object. Sa muling pagtatayo ng parent, inihahambing ng Flutter ang bagong widget sa kasalukuyang Element — kung ang uri at Key ay magkatugma, ang Element ay na-update at ang State ay nananatiling pareho.

Ang estado ay nagbabago lamang sa pamamagitan ng pagtawag ng setState, na nag-aabiso sa framework tungkol sa pangangailangan ng muling pagtatayo. Mahalagang maunawaan: ang setState ay hindi awtomatikong nagbabago ng estado — minamarkahan lamang nito ang widget bilang «marumi». Ang developer mismo ang nag-a-update ng mga field ng State sa callback na ipinasa sa setState. Pagkatapos ng callback, tinatawag ng Flutter ang build at ina-update ang UI.

Ayon sa Dart/Flutter team (Dart Language Specification, 2026), tinitiyak ng paghihiwalay na ito na ang lahat ng pagbabago ng estado ay nangyayari nang synchronously bago ang pagtawag ng build, na inaalis ang sitwasyon kung saan ang UI ay nagpapakita ng bahagyang na-update na data. Ito ang pangunahing mekanismo ng consistency ng interface sa Flutter.

Mga Halimbawa ng Code sa Dart

Isaalang-alang natin ang isang simpleng StatefulWidget — isang click counter ng button. Ipinapakita nito ang pangunahing pattern: paglikha ng State, initialization ng field sa initState, pagbabago sa pamamagitan ng setState:

dart
class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  @override
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _count = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Bilang: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Dagdagan'),
        ),
      ],
    );
  }
}

Halimbawa na may asynchronous na pag-load ng data at pamamahala ng lifecycle. Naglo-load ang StatefulWidget ng data mula sa network at nagpapakita ng status ng pag-load:

dart
class UserProfilePage extends StatefulWidget {
  final String userId;
  const UserProfilePage({super.key, required this.userId});

  @override
  State<UserProfilePage> createState() => _UserProfilePageState();
}

class _UserProfilePageState extends State<UserProfilePage> {
  UserModel? _user;
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadUser();
  }

  Future<void> _loadUser() async {
    final user = await UserService.fetchUser(widget.userId);
    setState(() {
      _user = user;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) return const CircularProgressIndicator();
    return Text('Kumusta, ${_user!.name}');
  }
}

Sa pangalawang halimbawa, mahalagang tandaan: sinisimulan ng initState ang isang asynchronous na operasyon, ngunit ang method mismo ay hindi asynchronous. Ang asynchrony ay naisasagawa sa pamamagitan ng async/await sa loob ng hiwalay na method na _loadUser, na nag-a-update ng estado sa pamamagitan ng setState pagkatapos makumpleto ang request. Tinitiyak ng approach na ito na ang widget ay wastong magpapakita ng loading indicator bago makatanggap ng data.

StatefulWidget vs StatelessWidget

Ang pagpili sa pagitan ng StatefulWidget at StatelessWidget ay hindi lamang tungkol sa pagkakaroon ng estado. Ang StatefulWidget ay nagbibigay ng kumpletong lifecycle na may mga method na initState, didChangeDependencies, didUpdateWidget at dispose, na kinakailangan para sa pagtatrabaho sa mga controller, animation at stream. Ang StatelessWidget naman ay walang mga method na ito at palaging mas magaan para sa framework.

Rekomendasyon ng Flutter team (Flutter docs, 2026) — bawasan ang bilang ng StatefulWidget sa application, sa pamamagitan ng pag-angat ng estado pataas sa tree (State Hoisting) o paggamit ng state management solutions (Riverpod, Bloc, Provider). Bawat StatefulWidget ay lumilikha ng State object na nabubuhay hanggang sa pagtanggal ng elemento — kung mas marami ang naturang widget, mas mataas ang memory load.

KriteryaStatefulWidgetStatelessWidget
EstadoNababagoHindi nababago
Lifecycle6 na yugtoBuild lamang
State objectGinawa nang hiwalayHindi kinakailangan
setStateMagagamitHindi magagamit
Mga subscriptioninitState/disposeHindi suportado
const constructorLimitadoGanap na suportado
Konsumo ng memoryaMas mataasMas mababa

Pagganap at Optimisasyon

StatefulWidget ay nangangailangan ng mas maraming resource kaysa StatelessWidget dahil sa pangangailangan na lumikha at mapanatili ang State object. Gayunpaman, ang tamang paggamit ng StatefulWidget ay hindi humahantong sa mga problema sa pagganap kung susundin ang ilang panuntunan. Una, iwasan ang malalim na nesting ng StatefulWidget — bawat antas ay nagdaragdag ng overhead para sa tree traversal. Pangalawa, hatiin ang kumplikadong StatefulWidget sa ilang simpleng widget, bawat isa ay responsable para sa sarili nitong bahagi ng estado.

Ayon sa Flutter Performance research (Flutter.dev, Pebrero 2026), ang pinakakaraniwang sanhi ng pagbaba ng FPS ay ang pagtawag ng setState sa parent widget na muling nagtatayo ng lahat ng descendants, kabilang ang StatelessWidget na hindi nagbago ang kanilang display. Ang solusyon — ilipat ang nababagong bahagi ng UI sa isang hiwalay na StatefulWidget, upang ang setState ay muling magtayo lamang ng minimum na kinakailangang widget.

Ang paggamit ng const sa loob ng State ay isa pang mahalagang technique. Kung ang child widget ay idineklara bilang const, hindi sila muling itatayo ng Flutter kapag tinawag ang setState sa parent. Pinababawasan nito ang load ng framework at pinaiikli ang oras ng rendering ng frame.

Iwasan ang madalas na setState

Bawat pagtawag ng setState ay nagti-trigger ng buong muling pagtatayo ng widget. Kung ang estado ay nagbabago nang may mataas na frequency (halimbawa, animation o data stream), isaalang-alang ang paggamit ng AnimatedBuilder, ValueListenableBuilder o StreamBuilder sa halip na manual na pagtawag ng setState. Ang mga widget na ito ay nag-o-optimize ng muling pagtatayo, ina-update lamang ang bahagi ng UI na talagang nagbago.

Mga Karaniwang Pagkakamali

Ang unang karaniwang pagkakamali sa StatefulWidget — pagtawag ng setState pagkatapos ng dispose. Kapag ang widget ay tinanggal mula sa tree, ang State ay itinuturing na patay at bawat pagtawag ng setState ay nagtatapon ng exception na «setState called after dispose». Kadalasan ito ay nangyayari kapag ang isang asynchronous na operasyon ay natapos pagkatapos tanggalin ang widget. Ang solusyon — suriin ang mounted flag bago tumawag ng setState o kanselahin ang mga asynchronous na operasyon sa dispose.

Ang pangalawang pagkakamali — pagsasagawa ng mabibigat na kalkulasyon sa build method. Dahil ang build ay tinatawag sa bawat setState at sa bawat muling pagtatayo ng parent, lahat ng kalkulasyon ay dapat na gaan hangga’t maaari. Kung kailangan magsagawa ng resource-intensive na operasyon — ilipat ito sa isang hiwalay na Isolate o i-cache ang resulta sa isang State field.

Ang pangatlong pagkakamali — hindi pagtawag ng super.initState() at super.dispose(). Kapag ni-override ang mga method na ito, ang developer ay obligadong tawagin ang parent implementation. Kung hindi ito gagawin, hindi mapamahalaan ng framework ang estado ng Element nang tama, na hahantong sa mga bug na mahirap mahanap.

Mga Rekomendasyon para sa Pag-iwas sa mga Pagkakamali

  • Palaging suriin ang mounted bago ang setState sa mga asynchronous callback
  • Huwag kalimutang tawagin ang super.initState() at super.dispose()
  • Huwag gumawa ng HTTP request nang direkta sa build — gamitin ang initState
  • Mag-unsubscribe mula sa lahat ng subscription sa dispose
  • Gumamit ng minimum na bilang ng StatefulWidget sa proyekto

Mga Madalas Itanong

Ano ang pagkakaiba ng StatefulWidget sa StatelessWidget?

StatefulWidget ay maaaring magbago ng estado nito sa pamamagitan ng setState, may lifecycle (initState, dispose) at lumilikha ng hiwalay na State object. Ang StatelessWidget ay hindi maaaring magbago ng estado at walang lifecycle method — ito ay nagpapakita lamang ng ipinasa na data.

Ilang beses tinatawag ang createState?

createState ay tinatawag nang eksaktong isang beses para sa bawat instance ng StatefulElement. Kahit na ang parent ay muling magtayo nang maraming beses, hangga’t ang uri at Key ng widget ay hindi nagbabago, ang createState ay hindi tinatawag — ang umiiral na State object ang ginagamit.

Ano ang mangyayari kung hindi tatawagin ang dispose?

Mga resource ay hindi mapapalaya: ang mga controller ay patuloy na gagana sa background, ang mga stream subscription ay mananatiling aktibo, ang mga timer ay hindi makakansela. Ito ay humahantong sa memory leaks at maaaring magdulot ng pagtawag ng setState pagkatapos ng dispose, na nagtatapon ng exception.

Maaari bang maging const ang StatefulWidget?

Oo, ang constructor ng StatefulWidget ay maaaring maging const. Gayunpaman, hindi ito nagbibigay ng parehong benepisyo tulad ng para sa StatelessWidget — ang State object ay gagawin pa rin sa unang paglalagay. Ang const ay nakakaapekto lamang sa widget mismo (light wrapper), hindi sa State.

Para saan ang didUpdateWidget method?

didUpdateWidget ay tinatawag kapag ang parent ay nagpapasa ng StatefulWidget na may mga bagong parameter. Ito ay kinakailangan upang i-synchronize ang estado sa bagong data — halimbawa, kung ang userId ay nagbago sa mga parameter, kailangang i-load ang profile ng bagong user.

Buod

  • StatefulWidget — widget na may nababagong estado na gumagamit ng hiwalay na State object para sa pag-iimbak ng data at pamamahala ng lifecycle
  • Lifecycle ay binubuo ng createState, initState, didChangeDependencies, build, didUpdateWidget at dispose, bawat isa ay may kanya-kanyang layunin
  • setState — ang tanging lehitimong paraan upang abisuhan ang framework tungkol sa pagbabago ng estado, pagkatapos nito ang build ay awtomatikong tinatawag
  • mounted — flag na dapat suriin bago ang setState sa mga asynchronous na operasyon upang maiwasan ang exception pagkatapos ng dispose
  • Pagganap — StatefulWidget ay nangangailangan ng mas maraming resource kaysa StatelessWidget; inirerekomenda na bawasan ang bilang nito sa pamamagitan ng paglipat ng estado sa mga panlabas na layer
  • Const child widget sa loob ng State ay nagpapahintulot na bawasan ang dami ng muling pagtatayo kapag tinawag ang setState, na nagpapabuti ng pagganap
  • Tamang pagpili — gamitin ang StatefulWidget lamang kapag ang widget ay kailangang mamahala ng nababagong data o asynchronous na operasyon

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din