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

Flutter Riverpod计数器UI不更新的原因是什么?

问题:Flutter + Riverpod 状态更新后UI未同步更新

尝试使用Flutter和Riverpod更新PopulationTracker的状态,控制台打印能看到state值变化,但UI上的计数器不更新。点击按钮后期望计数器显示+1,但实际无效果。

主Flutter计数器代码

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

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

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    var men = ref.watch(populationController).men.toString();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Example')),
        body: Center(
            child: Column(
          children: [
            Text("Amount of men is $men"),
            IconButton(
                onPressed: () {
                  ref.read(populationController.notifier).increaseMen();
                },
                icon: const Icon(Icons.plus_one))
          ],
        )),
      ),
    );
  }
}

Riverpod类定义文件代码

import 'package:flutter_riverpod/flutter_riverpod.dart';

class PopulationTracker {
  int women = 0;
  int men = 0;
}

class PopulationNotifier extends StateNotifier<PopulationTracker> {
  PopulationNotifier() : super(PopulationTracker());

  void increaseMen() {
    state.men += 1;
  }

  void increaseWomen() {
    state.women += 1;
  }

  void minusWomen() {
    state.women -= 1;
  }

  void minusMen() {
    state.men -= 1;
  }
}

final populationController =
    StateNotifierProvider<PopulationNotifier, PopulationTracker>(
        (ref) => PopulationNotifier());

原因与修复方案

核心原因

Riverpod的StateNotifier依赖状态对象的不可变性触发UI更新。当前代码直接修改了state.men的取值,没有创建新的PopulationTracker实例,Riverpod无法检测到状态变化,因此不会通知UI重建。

修复步骤

  1. 将PopulationTracker改为不可变类,用final修饰字段,并添加copyWith方法用于生成新实例
  2. 在PopulationNotifier的状态更新方法中,通过copyWith创建新的状态实例替换原有state

修改后的代码

import 'package:flutter_riverpod/flutter_riverpod.dart';

// 改为不可变类,添加copyWith方法
class PopulationTracker {
  final int women;
  final int men;

  PopulationTracker({this.women = 0, this.men = 0});

  // 复制现有实例并修改指定字段,生成新实例
  PopulationTracker copyWith({int? women, int? men}) {
    return PopulationTracker(
      women: women ?? this.women,
      men: men ?? this.men,
    );
  }
}

class PopulationNotifier extends StateNotifier<PopulationTracker> {
  PopulationNotifier() : super(PopulationTracker());

  void increaseMen() {
    // 生成新状态实例替换原state
    state = state.copyWith(men: state.men + 1);
  }

  void increaseWomen() {
    state = state.copyWith(women: state.women + 1);
  }

  void minusWomen() {
    state = state.copyWith(women: state.women - 1);
  }

  void minusMen() {
    state = state.copyWith(men: state.men - 1);
  }
}

final populationController =
    StateNotifierProvider<PopulationNotifier, PopulationTracker>(
        (ref) => PopulationNotifier());

修改后,每次状态变化都会生成新的PopulationTracker实例,Riverpod能检测到状态变更并触发UI重建,计数器即可正常更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:27:14