Riverpod:列表提供者没有重建
Riverpod: List provider is not rebuilding
当 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 示例:
您的小部件
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),
),
);
}
}
当 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 示例:
您的小部件
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),
),
);
}
}