Flutter中如何在try catch块用Get.off()根据当前页面跳转不同界面
问题描述
我有一个按钮会调用updateAllergy()函数,执行后会跳转至首页。现在希望另一个页面也设置调用该函数的按钮,但两个页面执行后需跳转至不同界面。请问能否根据当前所在页面指定跳转目标?我是Flutter初学者,以下是相关代码:
allergy_controller.dart
class AllergyController extends GetxController { static AllergyController get instance => Get.find(); RxBool isVegan = false.obs; RxBool isDairyFree = false.obs; RxBool isEgg = false.obs; RxBool isNut = false.obs; final userController = UserController.instance; final userRepository = Get.put(UserRepository()); GlobalKey<FormState> updateVeganFormKey = GlobalKey<FormState>(); GlobalKey<FormState> updateDairyFormKey = GlobalKey<FormState>(); GlobalKey<FormState> updateEggFormKey = GlobalKey<FormState>(); GlobalKey<FormState> updateNutFormKey = GlobalKey<FormState>(); // init user data when home appears @override void onInit() { initializeAllergy(); super.onInit(); } // fetch user record Future<void> initializeAllergy() async { isVegan.value = userController.user.value.preferences['Diet']['IsVegan'] ?? false; isDairyFree.value = userController.user.value.preferences['Diet']['IsDairyFree'] ?? false; isEgg.value = userController.user.value.preferences['Allergy']['IsEgg'] ?? false; isNut.value = userController.user.value.preferences['Allergy']['IsNut'] ?? false; } void saveVegan(bool? value) { isVegan.value = value ?? false; } void saveDairy(bool? value) { isDairyFree.value = value ?? false; } void saveEgg(bool? value) { isEgg.value = value ?? false; } void saveNut(bool? value) { isNut.value = value ?? false; } Future<void> updateAllergy() async { try { // form validation if (!updateVeganFormKey.currentState!.validate()) { updateVeganFormKey.currentState!.save(); return; } if (!updateDairyFormKey.currentState!.validate()) { updateDairyFormKey.currentState!.save(); return; } if (!updateEggFormKey.currentState!.validate()) { updateEggFormKey.currentState!.save(); return; } if (!updateNutFormKey.currentState!.validate()) { updateNutFormKey.currentState!.save(); return; } Map<String, dynamic> Preferences = { 'Allergy': { 'IsEgg': isEgg.value, 'IsNut': isNut.value, }, 'Diet': { 'IsVegan': isVegan.value, 'IsDairyFree': isDairyFree.value, }, }; // Update the 'isVegan' field within the 'Diet' map Preferences['Diet']['IsVegan'] = isVegan.value; Preferences['Diet']['IsDairyFree'] = isDairyFree.value; Preferences['Diet']['IsEgg'] = isEgg.value; Preferences['Diet']['IsNut'] = isNut.value; // Create the data to update in Firestore Map<String, dynamic> allergyData = { 'Preferences': Preferences, }; await userRepository.updateSingleField(allergyData); // update the rx user value userController.user.value.preferences['Diet']['IsVegan'] = isVegan.value; userController.user.update((user) { user?.preferences['Diet']['IsVegan'] = isVegan.value; }); userController.user.value.preferences['Diet']['IsDairyFree'] = isDairyFree.value; userController.user.update((user) { user?.preferences['Diet']['IsDairyFree'] = isDairyFree.value; }); userController.user.value.preferences['IsEgg'] = isEgg.value; userController.user.update((user) { user?.preferences['IsEgg'] = isEgg.value; }); userController.user.value.preferences['IsNut'] = isNut.value; userController.user.update((user) { user?.preferences['IsNut'] = isNut.value; }); // move to previous screen Get.off(() => const NavigationMenu()); } catch (e) { NLoaders.errorSnackBar(title: 'Oh Snap!', message: e.toString()); } } }
解决方案
当然可以实现,给你三种适合初学者的简单方案,基于你使用的GetX框架:
方案一:给updateAllergy添加跳转目标参数
直接修改函数,让它接收一个可选的跳转页面参数,默认值设为原来的首页,不同页面调用时传入对应目标页面即可。
修改后的updateAllergy函数:
// 添加可选参数,默认跳转首页 Future<void> updateAllergy({Widget? targetPage}) async { try { // 保留原有的表单验证、数据更新逻辑... // 使用传入的页面,无传入则用默认首页 final destination = targetPage ?? const NavigationMenu(); Get.off(() => destination); } catch (e) { NLoaders.errorSnackBar(title: 'Oh Snap!', message: e.toString()); } }
调用方式:
- 原页面(跳首页):
AllergyController.instance.updateAllergy(); - 新页面(比如跳设置页):
AllergyController.instance.updateAllergy(targetPage: const SettingsPage());
方案二:传递回调函数(更灵活)
如果需要在跳转前执行额外逻辑,或自定义跳转行为,可以传递一个回调函数:
修改后的函数:
Future<void> updateAllergy({VoidCallback? onSuccess}) async { try { // 保留原有的表单验证、数据更新逻辑... // 有回调则执行回调,否则默认跳首页 if (onSuccess != null) { onSuccess(); } else { Get.off(() => const NavigationMenu()); } } catch (e) { NLoaders.errorSnackBar(title: 'Oh Snap!', message: e.toString()); } }
调用方式:
- 原页面:
AllergyController.instance.updateAllergy(); - 新页面:
AllergyController.instance.updateAllergy(onSuccess: () { Get.off(() => const ProfilePage()); });
方案三:通过当前路由判断(不推荐初学者)
可以获取当前页面的路由名称,根据路由判断跳转目标,但需要给页面设置命名路由,对新手稍复杂:
Future<void> updateAllergy() async { try { // 保留原有的表单验证、数据更新逻辑... // 获取当前路由名称 final currentRoute = Get.currentRoute; if (currentRoute == '/allergy-settings') { Get.off(() => const NavigationMenu()); } else if (currentRoute == '/profile-edit') { Get.off(() => const ProfilePage()); } else { Get.off(() => const NavigationMenu()); } } catch (e) { NLoaders.errorSnackBar(title: 'Oh Snap!', message: e.toString()); } }
额外提示:优化原代码
- 冗余的Preferences赋值:初始化
Preferences时已经给Allergy和Diet设值,后面重复赋值且错误将IsEgg、IsNut加到Diet中,建议删除重复代码:
Map<String, dynamic> Preferences = { 'Allergy': { 'IsEgg': isEgg.value, 'IsNut': isNut.value, }, 'Diet': { 'IsVegan': isVegan.value, 'IsDairyFree': isDairyFree.value, }, }; // 删除以下四行重复代码 // Preferences['Diet']['IsVegan'] = isVegan.value; // Preferences['Diet']['IsDairyFree'] = isDairyFree.value; // Preferences['Diet']['IsEgg'] = isEgg.value; // Preferences['Diet']['IsNut'] = isNut.value;
- 冗余的userController更新:无需先修改
user.value再调用update,直接用update方法即可:
// 替换原四组更新代码 userController.user.update((user) { if (user != null) { user.preferences['Diet']['IsVegan'] = isVegan.value; user.preferences['Diet']['IsDairyFree'] = isDairyFree.value; user.preferences['Allergy']['IsEgg'] = isEgg.value; user.preferences['Allergy']['IsNut'] = isNut.value; } });
内容的提问来源于stack exchange,提问作者Safwan Norasidin
相关产品推荐
相关产品推荐

