我以为Riverpod只会在状态值不同的情况下触发重建,但事实证明,每次设置状态时它都会重建,尽管值是相同的.这是真的吗?

具体情况如下

@Freezed(genericArgumentFactories: true)
class Model with _$Model {
  const factory Model({required int id}) = _Model;
}

class Manager {
  static StateProvider<Model> modelProvider =
      StateProvider<Model>((ref) => Model(id: 1));
  Manager() {
    Stream.periodic(Duration(seconds: 1)).take(1000).listen((event) {
      ref.read(modelProvider.notifier).update((state) {
        var cloneState = state.copyWith();
        print("${state == cloneState}"); //This print true
        return cloneState;
      });
    });
  }
}

class TestWidget extends ConsumerWidget {
  const TestWidget();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    var model = ref.watch(Manager.modelProvider);
    print("model change......................"); //print every second
    return Text(model.id.toString());
  }
}

它显示TestWidget每秒钟重新构建一次,但我认为不应该这样,因为状态是一样的,尽管我再次设置了它. 我是不是遗漏了什么?谢谢.

推荐答案

这一切都是关于在引擎盖下使用identical(old, current)来比较各州.identical为其本身提出了以下内容:

/// Check whether two references are to the same object.
///
/// Example:
/// ```dart
/// var o = new Object();
/// var isIdentical = identical(o, new Object()); // false, different objects.
/// isIdentical = identical(o, o); // true, same object
/// isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
/// isIdentical = identical([1], [1]); // false
/// isIdentical = identical(const [1], const [1]); // true
/// isIdentical = identical(const [1], const [2]); // false
/// isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
/// ```
external bool identical(Object? a, Object? b);

以下是一个完整的复制运行示例:

void main() => runApp(const ProviderScope(child: MyApp()));

@Freezed(genericArgumentFactories: true)
class Model with _$Model {
  const factory Model({required int id}) = _Model;
}

class Manager {
  static StateProvider<Model> modelProvider = StateProvider<Model>((ref) {
    Stream.periodic(const Duration(seconds: 1)).take(1000).listen((event) {
      ref.read(modelProvider.notifier).update((state) {
        final cloneState = state.copyWith();
        // const cloneState = Model(id: 1); //The print true in both cases
        print("${state == cloneState}"); //This print true
        print("identical: ${identical(state, cloneState)}"); //This print false
        return cloneState;
      });
    });

    return const Model(id: 1);
  });
}

class MyApp extends ConsumerWidget {
  const MyApp();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    var model = ref.watch(Manager.modelProvider);
    print("model change......................"); //print every second
    return MaterialApp(home: Text(model.id.toString()));
  }
}

我对该示例进行了一些修改,但本质保持不变.只有通过应用‘const’,我们才能实现不重建.

Flutter相关问答推荐

如何在flutter中获得类似属性的float(CSS属性)

无法在Flatter中设计正确的布局

在Flutter TextField中计算子字符串位置

关闭模式,但再次打开时微件条件相同

如何在Flutter 中共享选定文本

如何使文本表格域在抖动中变圆?

在flutter中实现类似3D的可滚动堆叠分页列表

如何在巡逻测试期间重新启动dart 侧应用程序状态?

Flutter中不使用Container是否可以做margin

ScaffoldMessenger 在等待键下方不起作用

更新番茄计时器值不会触发 Flutter Riverpod 中的alert 声音

在参数为空时保持命名参数的默认值

Riverpod 2.3.6:AutoDisposeNotifier和ref.onDispose自动处理

为什么将 bloc 提供程序放在单独的文件/类中会引发错误?

为什么容器会填满整个空间?

函数中的变量在 Dart 中应该有什么关键字?

我几乎每次都将 Stateless Widget 与 BLoC 一起使用.我错了吗?

如何在flutter中共享容器和gridview之间的滚动条?

既然我们已经有了 Flutter 的内置 setState,为什么还要在 Flutter 中使用 BloC 或 Provider?

在 Flutter Bloc 中具有称为 status 的属性的一种状态或不同的状态,哪个更可取?