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

Riverpod调用add/editExercise报位置参数过多错误的解决方法

Riverpod调用方法提示参数过多的解决办法

错误信息

59:27: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
context.read(exerciseControllerProvider).addExercise(newExercise);

62:27: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
context.read(exerciseControllerProvider).editExercise(updatedExercise);

问题代码

ExerciseScreen 代码

import 'package:flutter/material.dart';
import 'package:song/core/models/exercise.dart';
import 'package:song/widgets/exercise_form.dart';
import 'package:song/core/models/exercise_types/front_back.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:song/core/providers/exercise_provider.dart';
import 'package:song/widgets/type_forms/type_controllers.dart';


class ExerciseScreen extends StatefulWidget {
  final Exercise? exercise;

  ExerciseScreen({Key? key, this.exercise}) : super(key: key);

  @override
  _ExerciseScreenState createState() => _ExerciseScreenState();
}

class _ExerciseScreenState extends State<ExerciseScreen> {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  TypeControllers? _controllers;

  @override
  void initState() {
    super.initState();
    _controllers = TypeControllers(
      questionController: TextEditingController(text: widget.exercise?.question ?? ''),
      answerController: TextEditingController(text: widget.exercise?.answer ?? ''),
    );
  }

  @override
  void dispose() {
    _controllers?.questionController.dispose();
    _controllers?.answerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.exercise == null ? 'Create Exercise' : 'Edit Exercise'),
      ),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: ExerciseForm(
          exercise: widget.exercise ?? FrontBack(id: '', front: '', back: ''),
          formKey: _formKey,
          controllers: _controllers!,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            _formKey.currentState!.save();
            if (widget.exercise == null) {
              Exercise newExercise = FrontBack(id: '', front: _controllers!.questionController.text, back: _controllers!.answerController.text);
              context.read(exerciseControllerProvider).addExercise(newExercise);
            } else {
              Exercise updatedExercise = (widget.exercise as FrontBack).copyWith(front: _controllers!.questionController.text, back: _controllers!.answerController.text);
              context.read(exerciseControllerProvider).editExercise(updatedExercise);
            }
            Navigator.pop(context);
          }
        },
        child: Icon(Icons.check),
      ),
    );
  }
}

Provider 代码

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:song/core/models/exercise.dart';
import 'package:state_notifier/state_notifier.dart';


class ExerciseController extends StateNotifier<List<Exercise>> {
  ExerciseController() : super([]);

  void addExercise(Exercise exercise) {
    state = [...state, exercise];
  }

  void editExercise(Exercise updatedExercise) {
    state = state.map((exercise) => exercise.id == updatedExercise.id ? updatedExercise : exercise).toList();
  }

  void removeExercise(String id) {
    state = state.where((exercise) => exercise.id != id).toList();
  }
}

final exerciseControllerProvider = StateNotifierProvider<ExerciseController, List<Exercise>>(
      (ref) => ExerciseController(),
);

TypeControllers 代码

import 'package:flutter/material.dart';

class TypeControllers {
  TextEditingController questionController;
  TextEditingController answerController;

  TypeControllers({required this.questionController, required this.answerController});
}

问题原因

这是Riverpod版本差异导致的API调用变化:

  • Riverpod 1.x中,context.read(provider)直接返回StateNotifier实例,可直接调用addExercise方法。
  • 但Riverpod 2.x中,context.read(provider)返回的是状态值(此处为List<Exercise>),而列表没有addExercise方法,因此会提示参数错误。

解决方案

方法1:快速修复 - 调用notifier属性获取控制器

直接修改调用代码,通过notifier属性拿到StateNotifier实例:

// 新增练习的代码改成:
context.read(exerciseControllerProvider.notifier).addExercise(newExercise);

// 编辑练习的代码改成:
context.read(exerciseControllerProvider.notifier).editExercise(updatedExercise);

方法2:推荐写法 - 使用ConsumerStatefulWidget

把原来的StatefulWidget改成ConsumerStatefulWidget,通过ref获取控制器,这是Riverpod 2.x的最佳实践:
修改后的ExerciseScreen代码:

import 'package:flutter/material.dart';
import 'package:song/core/models/exercise.dart';
import 'package:song/widgets/exercise_form.dart';
import 'package:song/core/models/exercise_types/front_back.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:song/core/providers/exercise_provider.dart';
import 'package:song/widgets/type_forms/type_controllers.dart';


class ExerciseScreen extends ConsumerStatefulWidget {
  final Exercise? exercise;

  ExerciseScreen({Key? key, this.exercise}) : super(key: key);

  @override
  _ExerciseScreenState createState() => _ExerciseScreenState();
}

class _ExerciseScreenState extends ConsumerState<ExerciseScreen> {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  TypeControllers? _controllers;

  @override
  void initState() {
    super.initState();
    _controllers = TypeControllers(
      questionController: TextEditingController(text: widget.exercise?.question ?? ''),
      answerController: TextEditingController(text: widget.exercise?.answer ?? ''),
    );
  }

  @override
  void dispose() {
    _controllers?.questionController.dispose();
    _controllers?.answerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.exercise == null ? 'Create Exercise' : 'Edit Exercise'),
      ),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: ExerciseForm(
          exercise: widget.exercise ?? FrontBack(id: '', front: '', back: ''),
          formKey: _formKey,
          controllers: _controllers!,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            _formKey.currentState!.save();
            // 通过ref获取控制器实例
            final exerciseController = ref.read(exerciseControllerProvider.notifier);
            if (widget.exercise == null) {
              Exercise newExercise = FrontBack(id: '', front: _controllers!.questionController.text, back: _controllers!.answerController.text);
              exerciseController.addExercise(newExercise);
            } else {
              Exercise updatedExercise = (widget.exercise as FrontBack).copyWith(front: _controllers!.questionController.text, back: _controllers!.answerController.text);
              exerciseController.editExercise(updatedExercise);
            }
            Navigator.pop(context);
          }
        },
        child: Icon(Icons.check),
      ),
    );
  }
}

两种方法都能解决问题,方法2更符合Riverpod 2.x的设计理念,后续维护也更方便。

内容的提问来源于stack exchange,提问作者Coding_noob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:15:02