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
相关产品推荐
相关产品推荐

