Flutter如何从其他Widget修改StatefulWidget内部的状态变量值
实现方案
实现思路
你需要实现的是跨组件状态同步(子组件触发父组件状态更新),最轻量化且适配当前场景的方案是通过「回调函数传参」实现:给子组件暴露可接收页面切换事件的回调参数,父组件将修改自身currentPage的逻辑传入该参数,子组件点击按钮时触发回调并把选中的页面标识传给父组件即可,完全支持跨dart文件调用。
步骤1:修改子组件AppBarHomeExtend定义
给子组件新增必填的回调参数,按钮点击时触发回调并传递对应的页面标识:
// 新增参数onPageSelected,类型为点击后向外传递选中页面字符串的回调 Widget AppBarHomeExtend({required ValueChanged<String> onPageSelected}) { return Container( height: 80, decoration: BoxDecoration( color: lightColor, boxShadow: [ BoxShadow(color: darkColor, blurRadius: 5), ], borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(35), bottomRight: Radius.circular(35))), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ HRButtons('All Messages', () => onPageSelected('all')), HRButtons('Groups', () => onPageSelected('groups')), HRButtons('Stories', () => onPageSelected('stories')), HRButtons('Calls', () => onPageSelected('calls')), ], ), ); }
步骤2:修改父组件HomeMobile的调用逻辑
在父组件调用AppBarHomeExtend时传入回调函数,收到子组件传递的页面标识后调用setState更新自身的currentPage变量:
import 'package:flutter/material.dart'; import 'package:messaging_service/components/app_bar.dart'; import 'package:messaging_service/components/home_pages/all_messages.dart'; import 'package:messaging_service/components/home_pages/stories.dart'; import 'package:messaging_service/components/search_bar.dart'; import 'package:messaging_service/components/strings.dart'; import 'package:messaging_service/components/style.dart'; class HomeMobile extends StatefulWidget { const HomeMobile({Key? key}) : super(key: key); @override _HomeMobileState createState() => _HomeMobileState(); } class _HomeMobileState extends State<HomeMobile> { var currentPage = 'all'; TextEditingController searchChatController = TextEditingController(); Widget build(BuildContext context) { return Scaffold( backgroundColor: lightColor, appBar: AppBarHomeMobile(context), body: SingleChildScrollView( child: Column( children: [ // 传入回调,接收子组件返回的页面标识后更新状态 AppBarHomeExtend( onPageSelected: (selectedPage) { setState(() { currentPage = selectedPage; }); }, ), const SizedBox( height: 10, ), // 可根据currentPage变量切换展示对应页面组件,示例如下: if (currentPage == 'all') AllMessagesPage(), if (currentPage == 'groups') GroupsPage(), if (currentPage == 'stories') StoriesPage(), if (currentPage == 'calls') CallsPage(), ], ), ), ); } }
可选优化:配合ValueListenableBuilder实现局部刷新
如果不想每次切换页面都调用setState刷新整个HomeMobile页面,可以把currentPage改为ValueNotifier类型,配合ValueListenableBuilder实现页面切换区域的局部刷新,跨文件也可以正常监听:
- 父组件中修改
currentPage定义:
// 原定义 var currentPage = 'all'; 改为: final ValueNotifier<String> currentPage = ValueNotifier('all');
- 回调中不需要调用
setState,直接修改value即可:
onPageSelected: (selectedPage) { currentPage.value = selectedPage; },
- 页面切换区域用
ValueListenableBuilder包裹:
ValueListenableBuilder<String>( valueListenable: currentPage, builder: (context, page, child) { switch(page) { case 'all': return AllMessagesPage(); case 'groups': return GroupsPage(); case 'stories': return StoriesPage(); case 'calls': return CallsPage(); default: return AllMessagesPage(); } }, )
内容的提问来源于stack exchange,提问作者AliMohammed Manzoor
相关产品推荐
相关产品推荐

