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);
},
),
),
);
}
}
有人可以向我解释为什么会发生这种情况吗?谢谢你。
试试这个
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) {
.......
详细说明