首页 > 解决方案 > Riverpod:列表提供程序未重建

问题描述

当' 的类型为时, Flutter Riverpod 不会通知Consumer状态更改,而相同的实现对于其他类型也可以正常工作。StateNotifierList

在这里,我提供了一个最小的可重现示例:

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
}

标签: flutterdartstate-managementriverpodflutter-state

解决方案


首先,您没有创建正确的提供者来收听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];
}

推荐阅读