为什么 Futurebuilder 小部件显示旧快照?

问题描述 投票:0回答:1
我有一个 Flutter Web 项目。我主要有两个页面:一个是我列出运动项目的页面,另一个是我修改特定运动项目的页面。为了导航,我使用

context.router.navigateNamed

 包的 
auto_route
 方法。

当我第一次导航到编辑页面时,一切正常,但如果我第二次导航到编辑页面(通过导航到列表页面并按另一个运动进行编辑),该页面将被重用,因为它已经在堆栈(如预期),但

Futurebuilder

无法正常工作(不显示加载,显示旧的
snapshot.data
,直接跳转到显示新的
snapshot.data
)。

这是我的代码:

class EditSportView extends StatefulWidget { final int id; const EditSportView({Key? key, @PathParam('id') required this.id}) : super(key: key); @override _EditSportViewState createState() => _EditSportViewState(); } class _EditSportViewState extends State<EditSportView> { late SportProvider sportProvider; late MenuProvider menuProvider; final GlobalKey<FormState> _keyForm = GlobalKey<FormState>(); late TextEditingController _nameController; final List<GameModeEntity> selectedGameModes = []; Timer? _timer; @override initState() { super.initState(); sportProvider = Provider.of<SportProvider>(context, listen: false); menuProvider = Provider.of<MenuProvider>(context, listen: false); _nameController = TextEditingController(); } @override void dispose() { _nameController.dispose(); _timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 8.0), child: SingleChildScrollView( physics: const ClampingScrollPhysics(), child: CustomCard( boxShadowBlurRadius: 0.0, child: Container( padding: const EdgeInsets.symmetric(horizontal: 5.0), child: FutureBuilder<List>( // <-------- The problem seems to be here future: Future.wait([ sportProvider.getSport(GetSportRequest(widget.id)), sportProvider.getAllGameModes(), ]), builder: (context, snapshot) { if (snapshot.hasData && !snapshot.data!.any((element) => element == null)) { SportEntity sport = snapshot.data![0]; _nameController.text = sport.name; List<GameModeEntity> gameModes = snapshot.data![1]; return Form( key: _keyForm, autovalidateMode: AutovalidateMode.onUserInteraction, child: Column( children: [ const CustomTextTitle( width: double.infinity, text: "Sport Settings"), const CustomDivider(), _nameTextFormField(), _gameModeSelectionFormField( gameModes, gameModes .map((e) => sport.gameModes! .any((element) => element.id == e.id)) .toList()), _createEventButton(context), _cancelEventButton(), ], ), ); } else { return const Center( child: CircularProgressIndicator(), ); } }, ), ), ), ), ); } Widget _nameTextFormField() { return CustomTextFormField( showCounter: true, controller: _nameController, isRequired: true, showPrefixIcon: false, showSuffixIcon: false, autofocus: true, topLabel: AppGlobals.nameText, textColor: Colors.black, validator: (String? value) { if (value == null || value.isEmpty) { return AppGlobals.fieldRequiredText; } if (!AppGlobals.onlyLettersNoSpaceRegExp.hasMatch(value)) { return AppGlobals.invalidNameText; } return null; }, onChanged: (String value) {}, ); } Widget _gameModeSelectionFormField( List<GameModeEntity> gms, List<bool> initialSelection) { return CustomGenericFormField<GameModeEntity>( topLabel: "Game Modes", items: gms.map((gm) => MultiSelectItem(gm, gm.label)).toList(), initialValue: gms .asMap() .entries .where((e) => initialSelection[e.key]) .map((e) => e.value) .toList(), validator: (values) { if (values?.isEmpty ?? true) { return "Select at lease one"; } return null; }, onTap: (values) { selectedGameModes.clear(); for (var element in values.where((e) => e != null)) { selectedGameModes.add(element!); } }, ); } Container _createEventButton(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(vertical: 10.0), child: SizedBox( width: 180, child: CustomOutlinedButton( padding: const EdgeInsets.symmetric(vertical: 5.0), text: "Update Sport", borderColor: AppGlobals.selectedSeparatorColor, isFilled: true, backgroundColor: AppGlobals.primaryColor, borderRadius: 5.0, textSize: 14, onPressed: () async { if (_keyForm.currentState!.validate()) { context.loaderOverlay.show(); UpdateSportRequest request = UpdateSportRequest( id: widget.id, name: _nameController.text, gameModes: selectedGameModes.map((e) => e.id).toList()); sportProvider.updateSport(request).then((value) { context.loaderOverlay.hide(); if (value ?? false) { showDialog( context: context, barrierDismissible: false, builder: (buildContext) { _timer = Timer(const Duration(seconds: 2), () { Navigator.of(buildContext).pop(); menuProvider .setCurrentPageUrl(RouteGlobals.listSportsRoute); context.router .navigateNamed(RouteGlobals.listSportsRoute); }); return const ConfirmationDialog( msg: AppGlobals.sportUpdateSuccessfullyText); }, ); } }); } }, ), ), ); } Container _cancelEventButton() { return Container( margin: const EdgeInsets.symmetric(vertical: 10.0), child: SizedBox( width: 180, child: CustomOutlinedButton( padding: const EdgeInsets.symmetric(vertical: 5.0), text: AppGlobals.cancelText, borderColor: AppGlobals.selectedSeparatorColor, isFilled: true, backgroundColor: Colors.black87, borderRadius: 5.0, textSize: 14, onPressed: () { menuProvider.setCurrentPageUrl(RouteGlobals.listSportsRoute); context.router.navigateNamed(RouteGlobals.listSportsRoute); }, ), ), ); } }
有人可以向我解释为什么会发生这种情况吗?谢谢你。

flutter flutter-dependencies flutter-provider
1个回答
0
投票
您应该提供 future(变量)而不是 future 函数。

试试这个

class _EditSportViewState extends State<EditSportView> { .... late Future<List> fetchData; @override void initState() { super.initState(); fetchData = Future.wait([ sportProvider.getSport(GetSportRequest(widget.id)), sportProvider.getAllGameModes(), ]); } ....... FutureBuilder<int>( future: fetchData, builder: (context, snapshot) { .......
详细说明

https://stackoverflow.com/a/77760361/3552066

© www.soinside.com 2019 - 2024. All rights reserved.