[英]Using riverpod for simple state management is not reading state changes at UI
我要轉移到 Riverpod 並從應該是一個非常簡單的 boolean state 管理開始切換應用程序主題。 我讀過很多“如何”做這件事,但沒有人關注基礎本身,使用過時的 API,使用不同的通知程序和提供者,並添加比需要更多的功能。 所以現在我迷路了。
版本:
簡單的故事:
StateNotifier
並在其中具有訪問器和修改器,用於 1 個 boolean 值問題:我可以通過打印看到 state 正在被更改,但是 state 更改時 UI 沒有更改。 我是否沒有為簡單的 boolean state 正確使用StateNotifier
和StateProvider
?
感謝您的任何見解和指導:代碼如下:
===
model class 帶訪問器/修改器
class RiverThemeDarkModel extends StateNotifier<bool> { RiverThemeDarkModel(): super(false) {} bool get isDark { print("model asked for dark status: ${state}"); return state; } toggleDark() { print("toggler has listeners: ${hasListeners}"); state =;state: print("toggled to; ${state}"); } set isDark(bool value) { state = value; } }
非常基本的應用程序 + 有狀態的小部件
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; void main() { runApp(ProviderScope(child: MyApp())); } final themeProvider = StateProvider((ref) => RiverThemeDarkModel()); class MyApp extends ConsumerWidget { const MyApp({Key? key}): super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final darkValueModel = ref.watch(themeProvider); print("consumer widget: dark value is ${darkValueModel.state} and listeners: ${darkValueModel.hasListeners}"); return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: darkValueModel.isDark? ThemeData.dark(): ThemeData.light(), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends ConsumerStatefulWidget { const MyHomePage({Key? key, required this.title}): super(key: key); final String title; @override ConsumerState<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends ConsumerState<MyHomePage> { @override Widget build(BuildContext context) { final darkValueModel = ref.watch(themeProvider); print("build of state"); return Scaffold( appBar: AppBar( title: Text(darkValueModel.isDark? "Dark Mode": "Light Mode"), actions: [ IconButton( icon: Icon(darkValueModel.isDark? Icons.nightlight_round: Icons.wb_sunny), onPressed: () { ref.read(themeProvider).toggleDark(); print("Got pressed button, after setting is ${ref.read(themeProvider).isDark} \n\n"); }) ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Something', ), ], ), ), ); } }
從您的代碼片段中,您在這里做了什么
final themeProvider = StateProvider((ref) => RiverThemeDarkModel());
是為您的 UI 提供對 class 的默認 state 的訪問權限,這是錯誤的。 因此,如果您將其更改為 true 並重新運行應用程序,它會更改主題。 現在您要做的是公開對 class 的 stateNotifier 的訪問權限,它會偵聽 class 的 state 更改並通知其偵聽器。 為此,您需要以這種方式使用 StateNotifierProvider ...
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
現在幫助你實現的代碼rest如下
為您的 Model。
class RiverThemeDarkModel extends StateNotifier<bool> {
RiverThemeDarkModel() : super(false) {}
//u don't need this 'getter' piece of code
bool get isDark {
print("model asked for dark status: ${state}");
return state;
}
toggleDark() {
print("toggler has listeners: ${hasListeners}");
state = !state;
print("toggled to: ${state}");
}
//neither do you need this
set isDark(bool value) {
state = value;
}
}
對於您的用戶界面...
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final darkValueModel = ref.watch(themeProvider);
print("consumer widget: dark value is ${darkValueModel.state} and listeners: ${darkValueModel.hasListeners}");
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: darkValueModel? ThemeData.dark() : ThemeData.light(),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends ConsumerState<MyHomePage> {
@override
Widget build(BuildContext context) {
final darkValueModel = ref.watch(themeProvider);
print("build of state");
return Scaffold(
appBar: AppBar(
title: Text(darkValueModel ? "Dark Mode" : "Light Mode"),
actions: [
IconButton(
icon: Icon(darkValueModel
? Icons.nightlight_round
: Icons.wb_sunny),
onPressed: () {
ref.read(themeProvider.notifier).toggleDark();
print("Got pressed button, after setting is ${ref.read(themeProvider)} \n\n");
})
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Something',
),
],
),
),
);
}
}
也查看文檔。 它闡明了一些您不會從大多數教程中得到的東西。 https://riverpod.dev/docs/concepts/reading
用這個
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
而不是這個
final themeProvider = StateProvider( (ref) => RiverThemeDarkModel());
對您的代碼進行小改動
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(ProviderScope(child: MyApp()));
}
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
class MyApp extends ConsumerWidget {
MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final darkValueModel = ref.watch(themeProvider);
print(
"consumer widget: dark value is ${ref.read(themeProvider.notifier).state} and listeners: ${ref.read(themeProvider.notifier).hasListeners}");
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme:darkValueModel
? ThemeData.dark()
: ThemeData.light(),
home: MyHomePage(title: 'Flutter Demo Home Page${ref.read(themeProvider.notifier).isDark}'),
);
}
}
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends ConsumerState<MyHomePage> {
@override
Widget build(BuildContext context) {
final darkValueModel = ref.watch(themeProvider);
print("build of state");
return Scaffold(
appBar: AppBar(
title: Text(ref.read(themeProvider.notifier).isDark
? "Dark Mode${widget.title}"
: "Light Mode"),
actions: [
IconButton(
icon: Icon(ref.read(themeProvider.notifier).isDark
? Icons.nightlight_round
: Icons.wb_sunny),
onPressed: () {
ref.read(themeProvider.notifier).toggleDark();
print(
"Got pressed button, after setting is ${ref.read(themeProvider.notifier).isDark} \n\n");
})
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Something ${ref.read(themeProvider.notifier).isDark} ",
),
],
),
),
);
}
}
class RiverThemeDarkModel extends StateNotifier<bool> {
RiverThemeDarkModel() : super(false) {}
bool get isDark {
print("model asked for dark status: ${state}");
return state;
}
toggleDark() {
print("toggler has listeners: ${hasListeners}");
state = !state;
print("toggled to: ${state}");
}
set isDark(bool value) {
state = value;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.