使用 riverpod 进行简单的状态管理并不是读取 UI 处的状态变化
Using riverpod for simple state management is not reading state changes at UI
我要转到 Riverpod 并开始使用应该是非常简单的布尔状态管理来切换应用程序主题。我读过很多“如何”做这件事,但 none 专注于基础知识本身,使用过时的 API,使用不同的通知程序和提供程序,并添加比需要更多的功能。所以现在我迷路了。
版本:
- shared_preferences: ^2.0.13
- flutter_riverpod: ^1.0.3
简单的故事:
- 一个模型 class 扩展了
StateNotifier
并且其中有访问器和修改器用于 1 个布尔值
- 非常基本的应用程序 + 有状态小部件
问题:我可以看到,通过打印,状态正在改变,但是 UI 没有改变到状态改变时。我没有正确使用 StateNotifier
和 StateProvider
作为简单的布尔状态吗?
感谢您的任何见解和指导!代码如下:
===
带有访问器/修改器的模型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 的默认状态,这是错误的。因此,如果您将其更改为 true 并重新运行应用程序,它会更改主题。现在您要做的是公开对 class 的 stateNotifier 的访问权限,它会侦听 class 的状态变化并通知其侦听器。为此,您需要以这种方式使用 StateNotifierProvider...
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
现在帮助您实现的其余代码如下
为您的模型。
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;
}
}
为了你的UI...
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());
而不是这个
最终主题提供者= 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;
}
}
我要转到 Riverpod 并开始使用应该是非常简单的布尔状态管理来切换应用程序主题。我读过很多“如何”做这件事,但 none 专注于基础知识本身,使用过时的 API,使用不同的通知程序和提供程序,并添加比需要更多的功能。所以现在我迷路了。
版本:
- shared_preferences: ^2.0.13
- flutter_riverpod: ^1.0.3
简单的故事:
- 一个模型 class 扩展了
StateNotifier
并且其中有访问器和修改器用于 1 个布尔值 - 非常基本的应用程序 + 有状态小部件
问题:我可以看到,通过打印,状态正在改变,但是 UI 没有改变到状态改变时。我没有正确使用 StateNotifier
和 StateProvider
作为简单的布尔状态吗?
感谢您的任何见解和指导!代码如下:
===
带有访问器/修改器的模型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 的默认状态,这是错误的。因此,如果您将其更改为 true 并重新运行应用程序,它会更改主题。现在您要做的是公开对 class 的 stateNotifier 的访问权限,它会侦听 class 的状态变化并通知其侦听器。为此,您需要以这种方式使用 StateNotifierProvider...
final themeProvider = StateNotifierProvider<RiverThemeDarkModel, bool>(
(ref) => RiverThemeDarkModel());
现在帮助您实现的其余代码如下
为您的模型。
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;
}
}
为了你的UI...
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());
而不是这个
最终主题提供者= 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;
}
}