当StateNotifier
的类型为List
时,Flutter riverpod不通知Consumer
状态变化,而对于其他类型,同样的实现工作得很好。
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),
),
);
}
}
对于add
方法,我尝试了很多方法来实现它,但都不起作用。
这是我尝试的:
1:直接添加:
add(int p) {
state.add(p);
}
2:我也尝试了这个答案中建议的解决方案:
add(int p) {
state = [...state, p];
}
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
}
首先,您没有创建正确的提供者来侦听StateNotifier
。你需要改变这个:
static final provider = StateProvider(
(ref) => CounterState(),
);
:
static final provider = StateNotifierProvider<CounterState, List<int>>(
(ref) => CounterState(),
);
关于不同类型的提供商,请参考Riverpod文档。
其次,您实际上并没有监视状态变化,而只是从通知器中获取状态对象。
改变这一行:
var count = watch(CounterState.provider.notifier).state.length;
:
final count = watch(CounterState.provider).length;
同样,您的增量方法对于StateNotifier
提供者是不正确的。请修改:
context.read(CounterState.provider.notifier).state.add(_count);
:
context.read(CounterState.provider.notifier).add(_count);
当状态改变时,它应该现在重建。但是,您确实需要一个add
方法的实现来实际更改状态对象本身。我建议使用你提到的第二种变体,在我看来,这是最好的方法:
add(int p) {
state = [...state, p];
}
@TmKVU解释得很好,所以我跳过这部分。你也可以关注riverpod文档
下面是我的riverPod示例:
- stateNotifierProvider
- stateProvider
小部件
import 'dart:math';
import 'package:stack_overflow/exports.dart';
class CounterState extends StateNotifier<List<int>> {
static final provider = StateNotifierProvider(
(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 MyHomePageSSSS extends ConsumerWidget {
@override
Widget build(BuildContext context, watch) {
void _incrementCounter() {
final _count = Random.secure().nextInt(100);
context.read(CounterState.provider.notifier).state =
context.read(CounterState.provider.notifier).state..add(_count);
}
final countprovider = watch(CounterState.provider);
return Scaffold(
appBar: AppBar(),
body: Center(
child: Text(
'You have pushed the button this many times: ${countprovider.length}',
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
}