Riverpod - 更新单个 属性 StateNotifier 时重建屏幕

Riverpod - Rebuild screen when updating single property of StateNotifier

在使用 Riverpod 作为我的状态管理工具时,我一直在使用我发现的反模式。我做了询问 的用户所做的:更新您想要更改的属性并添加 state = state。这个解决方案一直有效,直到 state_provider 包更新到 0.7.0 以上,之后这个解决方案完全停止工作。

我一直在尝试下面的线程中使用的解决方案,但这也不会为我重建 UI。谁能告诉我我在这里做错了什么?我觉得下面的解决方案应该可行,因为这基本上是您对任何其他状态管理包(例如 Redux)所做的。

我的状态模型,Notifier 和 Provider

import 'package:hooks_riverpod/hooks_riverpod.dart';

class Test {
  Test({this.prop1, this.prop2});

  String? prop1;
  int? prop2;
}

class TestNotifier extends StateNotifier<Test> {
  TestNotifier() : super(Test());
  void update() {
    state.prop2 ??= 0;
    state = state..prop2 = state.prop2! + 1;
  }
}

final StateNotifierProvider<TestNotifier, Test> testProvider =
    StateNotifierProvider((ref) => TestNotifier());

完整 main.dart 文件

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:practice_buddy/state/test_state.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends HookConsumerWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _testProvider = ref.watch(testProvider);
    final _testNotifier = ref.watch(testProvider.notifier);
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '${_testProvider.prop2 ?? 0}',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _testNotifier.update(),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Pubspec 显示包版本

dependencies:
  cloud_firestore: ^3.1.7
  firebase_auth: ^3.3.6
  firebase_core: ^1.12.0
  flutter:
    sdk: flutter
  flutter_hooks: ^0.18.2
  hooks_riverpod: ^1.0.3

我的Flutter版本是2.8.1.

这可以通过在更新时传递一个新实例来解决。

 void update() {
    state.prop2 ??= 0;
    state = state.copyWith(prop2: state.prop2! + 1);
  }

在模型 class copyWith 构造函数上。

  Test copyWith({
    String? prop1,
    int? prop2,
  }) {
    return Test(
      prop1: prop1 ?? this.prop1,
      prop2: prop2 ?? this.prop2,
    );
  }