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

Flutter Riverpod跨页面无法读取更新状态的问题咨询

Riverpod跨页面状态不更新问题解决

问题场景

首次使用Riverpod,在HomePage中修改状态后能正常读取更新值,但跳转至其他页面后无法获取最新状态。以下是相关代码:

CompanyModel定义

class CompanyModel {
  String? dataArea;

  CompanyModel({this.dataArea});
}

StateNotifier定义

class RiverpodCompany extends StateNotifier<CompanyModel> {
  RiverpodCompany() : super(CompanyModel(dataArea: "Test"));

  updateDataArea(value) {
    return state = CompanyModel(dataArea: value);
  }
}

HomePage代码

final riverpodChangeCompany =
    StateNotifierProvider<RiverpodCompany, CompanyModel>(
  (ref) => RiverpodCompany(),
);

class HomePage extends ConsumerWidget {
  const HomePage({super.key});
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    TextEditingController tfController = TextEditingController();
    final company = ref.watch(riverpodChangeCompany);
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(company.dataArea.toString()),
            SizedBox(
              width: 200,
              child: TextField(
                controller: tfController,
              ),
            ),
            const SizedBox(
              height: 15,
            ),
            SizedBox(
              width: 100,
              height: 100,
              child: GestureDetector(
                onTap: () {
                  ref
                      .watch(riverpodChangeCompany.notifier)
                      .updateDataArea(tfController.text);
                  print(tfController.text);
                  Navigator.pushNamed(context, AppRoutesNames.finalpage);
                },
                child: const Card(
                  color: Colors.blueAccent,
                  child: Center(child: Text("OK")),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

问题原因与修复方案

核心原因

  1. 状态类未遵循不可变设计,可能导致状态更新逻辑异常
  2. 其他页面未正确监听Provider的状态变化
  3. HomePage中存在不必要的控制器重建和错误的Provider调用方式

修复步骤

1. 重构状态类与Provider

将状态类改为不可变设计,并把Provider移至全局可访问位置(比如单独的providers.dart文件),确保所有页面能引用同一个Provider实例:

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

class CompanyModel {
  final String? dataArea; // 改为final,确保状态不可变

  CompanyModel({this.dataArea});
}

class RiverpodCompany extends StateNotifier<CompanyModel> {
  RiverpodCompany() : super(CompanyModel(dataArea: "Test"));

  // 指定参数类型,规范方法
  void updateDataArea(String value) {
    state = CompanyModel(dataArea: value); // 直接赋值状态,无需return
  }
}

// 全局Provider定义
final riverpodChangeCompany = StateNotifierProvider<RiverpodCompany, CompanyModel>(
  (ref) => RiverpodCompany(),
);

2. 在目标页面正确监听状态

跳转后的页面需使用ConsumerWidget,通过ref.watch监听状态变化,确保UI自动更新:

// final_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers.dart';

class FinalPage extends ConsumerWidget {
  const FinalPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 用ref.watch获取最新状态,自动监听变化
    final company = ref.watch(riverpodChangeCompany);
    
    return Scaffold(
      appBar: AppBar(title: const Text("Final Page")),
      body: Center(
        child: Text("更新后的dataArea: ${company.dataArea ?? '未设置'}"),
      ),
    );
  }
}

3. 修正HomePage的问题

  • 将TextEditingController移至状态类中,避免每次build重建并正确销毁
  • 触发状态更新时使用ref.read而非ref.watch,减少不必要的UI重建:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'providers.dart';

class HomePage extends ConsumerStatefulWidget {
  const HomePage({super.key});

  @override
  ConsumerState<HomePage> createState() => _HomePageState();
}

class _HomePageState extends ConsumerState<HomePage> {
  late final TextEditingController tfController = TextEditingController();

  @override
  void dispose() {
    tfController.dispose(); // 销毁控制器,避免内存泄漏
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final company = ref.watch(riverpodChangeCompany);
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(company.dataArea.toString()),
            SizedBox(
              width: 200,
              child: TextField(
                controller: tfController,
              ),
            ),
            const SizedBox(height: 15),
            SizedBox(
              width: 100,
              height: 100,
              child: GestureDetector(
                onTap: () {
                  // 仅触发更新时用ref.read,无需监听状态
                  ref.read(riverpodChangeCompany.notifier).updateDataArea(tfController.text);
                  Navigator.pushNamed(context, AppRoutesNames.finalpage);
                },
                child: const Card(
                  color: Colors.blueAccent,
                  child: Center(child: Text("OK")),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

关键注意事项

  • 状态类必须是不可变的,所有成员变量用final修饰,确保状态更新时生成新实例
  • Provider需定义在全局范围,避免页面间引用不同的Provider实例
  • 读取状态用ref.watch(需要UI随状态更新),触发操作用ref.read(仅执行动作)
  • 页面需继承ConsumerWidget或ConsumerStatefulWidget以获取WidgetRef

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:15:05