今天我們要介紹的是 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'),
),
],
),
),
);
}
}
我們明天見~