You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Riverpod自动生成的StateNotifier提供者不是StateNotifierProvider?

问题描述

我正在使用Riverpod架构开发Flutter应用,需要用StateNotifier跟踪一个用于保存多屏表单当前页码的int值。以下是我的StateNotifier代码:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'multi_step_controller.g.dart';

class MultiStepFormController extends StateNotifier<int> {
  MultiStepFormController() : super(0);

  void next() => state += 1;
  void previous() => state -= 1;
  void reset() => state = 0;
  void setIndex(int index) => state = index;
}

我尝试使用Riverpod 3.0语法自动生成该类的提供者,代码如下(已执行构建生成part文件):

@Riverpod(keepAlive: true)
MultiStepFormController multiStepFormController(MultiStepFormControllerRef ref) {
  return MultiStepFormController();
}

但读取int值时出现错误:pageController.jumpToPage(currentIndex); The argument type 'MultiStepController' can't be assigned to the parameter type 'int'.

之后我手动编写了提供者代码:

final multiStepFormControllerProvider = StateNotifierProvider<MultiStepFormController, int>((ref) { return MultiStepFormController(); });

此时代码可正常运行。我想了解为何自动生成的提供者与手动编写的效果不同,以便未来更好地使用Riverpod自动生成代码。

原因分析与解决方案

核心差异:Provider类型不匹配

你手动编写的是StateNotifierProvider<MultiStepFormController, int>,这类Provider会暴露StateNotifier内部的状态值(即int类型)给消费者;而你用@Riverpod注解直接返回MultiStepFormController实例时,生成的是Provider<MultiStepFormController>,它直接暴露的是StateNotifier对象本身,而非其内部的int状态。

这就导致你读取自动生成的Provider时,拿到的是控制器实例而非页码数值,自然触发类型不匹配错误。

正确生成StateNotifierProvider的写法

要让Riverpod自动生成对应StateNotifierProvider的代码,有两种规范写法:

写法一:返回StateNotifierProvider实例

@Riverpod(keepAlive: true)
StateNotifierProvider<MultiStepFormController, int> multiStepFormController(MultiStepFormControllerRef ref) {
  return StateNotifierProvider((ref) => MultiStepFormController());
}

写法二:继承_$XXX类(更简洁的Riverpod推荐写法)

直接将控制器逻辑整合到注解类中,Riverpod会自动生成对应的StateNotifierProvider:

@Riverpod(keepAlive: true)
class MultiStepFormController extends _$MultiStepFormController {
  @override
  int build() => 0;

  void next() => state += 1;
  void previous() => state -= 1;
  void reset() => state = 0;
  void setIndex(int index) => state = index;
}

这种写法生成的multiStepFormControllerProvider类型为StateNotifierProvider<MultiStepFormController, int>,消费者读取时直接拿到int类型的状态值,调用方法时通过ref.read(multiStepFormControllerProvider.notifier)获取控制器实例。

使用示例对比

  • 读取状态值(int):

    final currentIndex = ref.watch(multiStepFormControllerProvider);
    pageController.jumpToPage(currentIndex); // 正常工作
    
  • 调用控制器方法:

    ref.read(multiStepFormControllerProvider.notifier).next();
    

内容的提问来源于stack exchange,提问作者sylvain gut.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 17:56:21