【问题标题】:Riverpod: List provider is not rebuildingRiverpod:列表提供程序未重建
【发布时间】:2021-10-13 03:16:05
【问题描述】:

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:我也尝试了this answer中建议的解决方案:

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
}

【问题讨论】:

    标签: flutter dart state-management riverpod flutter-state


    【解决方案1】:

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

    【讨论】:

    • 当我删除 .state 并将行设为 final count = watch(CounterState.provider).length; 时,我收到此错误:The getter 'length' isn't defined for the type 'StateController&lt;CounterState&gt;'. Try importing the library that defines 'length', correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
    • 啊,我看到您的提供商是StateProvider,而不是StateNotifierProvider。我将编辑答案以包含此修复程序
    • 你更新到StateNotifierProvider了吗?
    • 您是否也更新了您的增量方法?这当然也不适用于 StateNotifier 对象
    • 我觉得你对StateProviderStateNotifierProvider 有点困惑。您正在创建一个StateNotifier 类,因此您需要一个StateNotifierProvider。您可以在the documentation中找到更多信息
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-05-30
      • 2021-11-29
      • 2022-01-07
      • 2021-02-25
      • 1970-01-01
      • 2021-01-19
      • 2022-11-11
      • 2013-07-07
      • 1970-01-01
      相关资源
      最近更新 更多