Riverpod:列表提供程序未重建



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),
),
);
}
}

最新更新