Adn*_*nan 5 state-management dart flutter flutter-state riverpod
当 的 类型为 时, Flutter Riverpod 不会通知Consumer
状态变化,而相同的实现对于其他类型来说效果很好。StateNotifier
List
在这里,我提供了一个最小的可重现示例:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
home: MyHomePage(),
),
);
}
}
class CounterState extends StateNotifier<List<int>> {
static final provider = StateProvider(
(ref) => CounterState(),
);
int get last {
print('last');
return state.last;
}
int get length {
print('len');
return state.length;
}
// the body of this will be provided below
add(int p) {}
CounterState() : super(<int>[0]);
}
class MyHomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, watch) {
void _incrementCounter() {
final _count = Random.secure().nextInt(100);
context.read(CounterState.provider.notifier).state.add(_count);
}
var count = watch(CounterState.provider.notifier).state.length;
return Scaffold(
appBar: AppBar(),
body: Center(
child: Text(
'You have pushed the button this many times: $count',
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
至于add
方法,我尝试了很多方法实现,但都行不通。
这是我尝试过的:
1:直接添加即可:
add(int p) {
state.add(p);
}
Run Code Online (Sandbox Code Playgroud)
2:我还尝试了这个答案中建议的解决方案:
add(int p) {
state = [...state, p];
}
Run Code Online (Sandbox Code Playgroud)
3:我尝试完全销毁该列表,然后重新分配它:
add(int p) {
final _state = [];
// copy [state] to [_state]
for (var item in state) {
_state.add(item);
}
// empty the state
state = [];
// add the new element
_state.add(p);
// refill [state] from [_state]
for (var item in _state) {
state.add(item);
}
print(state.length); // it continues until here and prints
}
Run Code Online (Sandbox Code Playgroud)
首先,您没有创建正确的提供程序来收听StateNotifier
. 你需要改变这个:
static final provider = StateProvider(
(ref) => CounterState(),
);
Run Code Online (Sandbox Code Playgroud)
对此:
static final provider = StateNotifierProvider<CounterState, List<int>>(
(ref) => CounterState(),
);
Run Code Online (Sandbox Code Playgroud)
请参阅有关不同类型提供程序的 Riverpod 文档。
其次,您实际上并没有监视状态更改,而只是从通知程序获取状态对象。
更改这一行:
var count = watch(CounterState.provider.notifier).state.length;
Run Code Online (Sandbox Code Playgroud)
对此:
final count = watch(CounterState.provider).length;
Run Code Online (Sandbox Code Playgroud)
另外,您的增量方法对于提供商来说不正确StateNotifier
。请更改此:
context.read(CounterState.provider.notifier).state.add(_count);
Run Code Online (Sandbox Code Playgroud)
对此:
context.read(CounterState.provider.notifier).add(_count);
Run Code Online (Sandbox Code Playgroud)
当状态发生变化时,它现在应该重建。但是,您确实需要一个add
实际更改状态对象本身的方法的实现。我建议您提到的第二种变体,在我看来这是最好的方法:
add(int p) {
state = [...state, p];
}
Run Code Online (Sandbox Code Playgroud)