在Flutter裡通通都是widget
在官方範例中也常見到他畫出APP的Widget tree
在使用過statefulWidget後
會發現有些數值只存在於子widget的狀態中
使用上方widget tree圖片舉例
商品目錄MyCatalog , 將商品加入購物車
購物車MyCart,就得要顯示剛剛那件物品
經過這點會發現MyCatalog MyCart各自的statefulWidget
怎麼能共用資料讓購物車在兩個畫面都能操作
此處會使用
Counter:點按鈕增加畫面上數字的demo
我們開始看範例
ChangeNotifier
: 繼承後代表可以去監聽Counter
value數值的變化increment
: 使value增加 notifyListeners()
讓有使用Consumer的widget更新
class Counter with ChangeNotifier {
int value = 0;
void increment() {
value += 1;
notifyListeners();
}
}
ChangeNotifierProvider
表示你的Counter能夠在ShopView上使用@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
initialRoute: '/',
routes: {
'/': (context) => const MainView(),
BASIC: (context) => const BasicView(),
IMAGEPICKER: (context) => const ImagePickerPage(),
CALLBACK: (context) => const CallBackView(),
//p1
SHOP: (context) => ChangeNotifierProvider(
create: (context) => Counter(),
child: const ShopView(),
),
},
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
);
}
Consumer
加在 顯示Counter value的widget上context.read<Counter>()
讀取Counterclass ShopView extends StatefulWidget {
const ShopView({Key? key}) : super(key: key);
@override
State<ShopView> createState() => _ShopViewState();
}
class _ShopViewState extends State<ShopView> {
@override
Widget build(BuildContext context) {
var snackBar = SnackBar(
content: const Text(
'您正離開商品頁唷!',
),
action: SnackBarAction(
label: '知道了',
onPressed: () => showDialog(
barrierDismissible: true,
context: context,
builder: (context) => Container(
alignment: Alignment.center,
child: const DefaultTextStyle(
style: TextStyle(fontSize: 30),
child: Text('知道就知道'),
),
),
),
),
);
return Scaffold(
appBar: AppBar(
title: Text(MyApp.SHOP.replaceAll('/', '')),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('個人頁面'),
onTap: (() => Navigator.pop(context)),
),
ListTile(
title: const Text('離開'),
onTap: () => {
Navigator.popAndPushNamed(context, '/'),
ScaffoldMessenger.of(context).showSnackBar(snackBar),
},
),
],
),
),
body: Container(
color: Colors.black38,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//p2
Consumer<Counter>(
builder: ((context, couter, child) => Text('Count is: ${couter.value}')),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () {
//p3
var counter = context.read<Counter>();
counter.increment();
},
child: const Icon(Icons.add),
),
],
),
],
),
),
);
}
}