Last Updated on 2021-05-18 by Clay
在剛學習著使用 Flutter 開發 App 的時期,一定會在撰寫界面的時候疑惑:不知道現在究竟該使用 StatefulWidget?還是應該要使用 StatelessWidget?
其實使用場合非常簡單就能分辨:
- StatelessWidget: 頁面創立好之後就不會更動。
- StatefulWidget: 頁面上的元件與使用者會有互動、元件樣式可能會改變。
今天我就簡單地紀錄每次使用 IDE 打開專案,都能看到『點擊按鈕,使畫面中央數字增加』—— 這個簡單 DEMO 的程式碼是如何運作。當然,既然我們改變了畫面中央的數字,那麼這想必得使用能使元件『改變』的『StatefulWidget』才行。(這個 DEMO 我有在《Flutter 學習心得筆記 (0) 下載 Intellij IDEA》當中測試過。)
若是對 Flutter 學習有興趣,可以參閱他們的官方 Tutorial: https://flutter.dev/docs/reference/tutorials
StatefulWidget
事先聲明,我有刪除一些不必要的程式碼,比如 AppBar 以及名稱傳遞之類的程式,力求最小化的範例程式。
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } }
這邊我們定義了程式的進入點(main()),這裡我們使用 StatelessWidget,應該這邊以後並不會再改變了。
以下我們接著定義 MyHomePage()。
class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); }
這裡我們就要使用 StatefulWidget 了。我們使用 "createState()" 這個函式來實例化我們接下來要撰寫的頁面,在這之後,若是我們需要重繪頁面,就使用 "setState()" 函式來重繪頁面。
接下來終於要來製作我們 App 最主要的界面了:一個『顯示點擊按鈕次數的文字』、一個『按鈕』。
class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), ); }
Output:
別忘了,一開始我們應該使用 _counter 變數來儲存我們點擊次數,有下底線 "_" 的變數都是私有變數。然後我們定義一個 function _incrementCounter() 來增加 _counter,並將其放到下面點擊按鈕觸發的『事件』裡。
這樣一來,我們『點擊按鈕,使畫面中央數字變化』的簡單 DEMO 就完成了!
也可以更改元件顏色
接下來我們來更改除了點擊數字以外的元件屬性吧?
跟上方的 DEMO 一樣依樣畫葫蘆,我們將改變的物件更改為『Color』,並賦予畫面當中的文字。
這樣一來,就變成我們點擊按鈕就會改變文字顏色了:
import 'dart:math'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { Color _color = Color.fromARGB(255, 0, 0, 200); void _colorChange() { setState(() { _color = Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)); }); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', style: TextStyle(color: _color), ), Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _colorChange, tooltip: 'Increment', child: Icon(Icons.add), ), ); } }
Output:
可以看到,每次點擊按鈕之後,中央文字都會改變。
以上就是關於 Flutter 當中 StatefulWidget 的簡單紀錄。之所以會寫這個是因為我今天想要將從前寫過的 App 從 Android Studio (Java) 移植到 Flutter 上 (我要拋棄 Java 啦!)
然後,我熊熊忘記 StatefulWidget 該怎麼寫......對啦,就是 createState() 那一段。