今天我們要介紹的是 Flutter 中的狀態管理。它關係到如何有效地管理和處理應用程式中的數據變化,以及如何根據這些變化來更新 UI。
而在第3天中我們有介紹過 StatelessWidget 和 StatefulWidget,我們知道了 StatelessWidget 是靜態的,因此今天所有的狀態管理都是寫在 StatefulWidget 之中。
以下是幾種常見的狀態管理方法:
setState 主要是更新 widget 的狀態,並使得 UI 重新建構。這是因為 Flutter 是一個聲明式框架,你需要告訴框架什麼時候應該重新繪製界面。通常在需要更改頁面內容時使用,例如按鈕點擊、表單提交或計時器等等。
int counter = 0;
void incrementCounter() {
  setState(() {
    counter++;
  });
}
InheritedWidget 是 Flutter 中的一種特殊的 widget,用於在 widget 中共享和傳遞狀態。它主要用於在 widget 中向下傳遞數據,讓子 widget 能夠更快的使用這些數據,藉此提高性能。
InheritedWidget 允許將狀態或數據從一個 widget 傳遞到 widget 樹中的其他 widget。這樣,任何需要這些數據的子 widget 都可以方便地訪問它們。
import 'package:flutter/material.dart';
// 自定義 InheritedWidget
class MyInheritedWidget extends InheritedWidget {
  final int data;
  MyInheritedWidget({required this.data, required Widget child}) : super(child: child);
  // 靜態方法來獲取 MyInheritedWidget 實例
  static MyInheritedWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  }
  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return data != (oldWidget as MyInheritedWidget).data;
  }
}
// 使用 InheritedWidget 的範例
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final myData = MyInheritedWidget.of(context)?.data;
    return Center(
      child: Text('Data: $myData'),
    );
  }
}
Provider 是 Flutter 中的一個常用狀態管理解決方案,並提供了簡單的 API 來進行依賴注入、狀態管理和通知。比直接使用 InheritedWidget 來的簡便。
dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0
import 'package:flutter/material.dart';
class Counter with ChangeNotifier {
 int _count = 0;
 int get count => _count;
 void increment() {
   _count++;
   notifyListeners();
 }
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
 runApp(
   ChangeNotifierProvider(
     create: (context) => Counter(),
     child: MyApp(),
   ),
 );
}
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: HomeScreen(),
   );
 }
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer<Counter>(
              builder: (context, counter, child) {
                return Text(
                  'Count: ${counter.count}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            ElevatedButton(
              onPressed: () {
                Provider.of<Counter>(context, listen: false).increment();
              },
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}
我們明天見~