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

Riverpod状态变更时组件不刷新问题求助

关于Flutter Riverpod状态变更后组件不重渲染的问题

在Flutter中使用Riverpod时遇到异常:状态发生变更时,组件并未触发重渲染,始终停留在初始标签页。已尝试以下方案但均未解决:

  • 使用StateProvider、NotifierProvider等不同的Riverpod状态提供者;
  • 通过方法调用更新状态而非直接赋值state;
  • 更换GNav导航栏为悬浮按钮组件;
  • 使用Consumer组件替代ConsumerWidget。

可行代码示例

该方案可正常运行:

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

final tabProvider = StateNotifierProvider<TabEncap, int>((ref) => TabEncap());

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

  void set(int i) {
    print(state);
    state = i;
  }
}

class UserPage extends ConsumerWidget {
  const UserPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // Watch the tabProvider and get its value
    final currentIndex = ref.watch(tabProvider);

    print("render");

    final List<Widget> _children = [
      Text("zero"),
      Text("one"),
    ];

    return Scaffold(
      body: _children[currentIndex],
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          FloatingActionButton(
            onPressed: () {
              ref.read(tabProvider.notifier).set(0);
              print(ref.read(tabProvider.notifier).state);
            },
            child: Text("Zero"),
          ),
          SizedBox(width: 16),
          FloatingActionButton(
            onPressed: () {
              ref.read(tabProvider.notifier).set(1);
              print(ref.read(tabProvider.notifier).state);
            },
            child: Text("One"),
          ),
        ],
      ),
    );
  }
}

问题代码示例

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_nav_bar/google_nav_bar.dart'; 


final tabProvider = StateProvider<int>((ref) => 0);

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {

    // Watch the currentIndexProvider and get its value
    var currentIndex = ref.watch(tabProvider.notifier).state;

    print("render");
      
    final List<Widget> _children = [
      Text("zero"),
      Text("one")
    ];

    return Scaffold(
      body: IndexedStack(index: currentIndex, children: _children,),
      bottomNavigationBar: GNav(
        tabs: const [
          GButton(
            icon: Icons.add,
            text: 'zero',
          ),
          GButton(
            icon: Icons.person,
            text: 'one',
          ),
        ],

        selectedIndex: currentIndex,
        onTabChange: (index) => { 
          ref.read(tabProvider.notifier).state = index, 
          print(ref.read(tabProvider.notifier).state)
        }

      ),
    );
  }
}

运行输出

render
0
1
0
1
0

问题原因及解决办法

问题代码中的核心错误在于监听对象错误:

var currentIndex = ref.watch(tabProvider.notifier).state;

这里ref.watch监听的是tabProvider.notifier(状态通知器实例),而不是tabProvider本身的状态值。由于通知器实例不会随状态变更而改变,所以即使状态state更新了,组件也不会收到重渲染通知。

解决办法是直接监听tabProvider获取状态值:

final currentIndex = ref.watch(tabProvider);

修改后,当tabProvider的状态发生变化时,ref.watch会触发组件重新构建,从而更新页面内容和导航栏选中状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:50:32