Flutter GetX路由异常:详情页无法加载新invoiceId数据
问题原因
GetX 的 Get.put<T>() 方法默认会复用已存在的同类型 Controller 实例。首次点击卡片时,你注入了对应 invoiceId 的 DetailsPaymentHistoryController;返回列表页后再次点击其他卡片,Get.put() 不会替换已存在的旧实例,导致详情页仍使用旧的 invoiceId 加载数据。而 Get.offNamed() 会替换当前路由栈,所以返回时跳过了列表页,不符合需求。
解决方案
方案1:强制替换 Controller 实例 + 返回刷新列表
修改卡片的点击事件,给 Get.put() 添加 force: true 参数强制覆盖旧实例,同时通过 then() 回调在返回列表页时触发刷新:
InkWell( onTap: () { // 强制替换已存在的Controller实例 Get.put<DetailsPaymentHistoryController>( DetailsPaymentHistoryController( paymentHistoryApi: PaymentHistoryApi(), invoiceId: payment.invoiceId!.toString()), force: true, // 关键参数:强制覆盖旧实例 ); // 跳转后等待返回,触发列表刷新 Get.toNamed(Routes.detailsHistoryPayment).then((_) { // 获取列表页Controller并调用刷新方法 Get.find<PaymentHistoryListController>().refreshList(); }); }, child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Text( 'More Details', style: getSemiBoldStyle( color: Colormanager.primary, fontSize: FontSize.s15), ), const SizedBox(width: AppSize.s4), Icon(Icons.read_more, color: Colormanager.darkPrimary), ], ), )
方案2:先删除旧实例再注入新的
如果不想用 force: true,可以先删除已存在的同类型 Controller,再注入新实例:
InkWell( onTap: () { // 删除已存在的DetailsPaymentHistoryController实例 Get.delete<DetailsPaymentHistoryController>(); // 注入新的Controller实例 Get.put<DetailsPaymentHistoryController>( DetailsPaymentHistoryController( paymentHistoryApi: PaymentHistoryApi(), invoiceId: payment.invoiceId!.toString()), ); Get.toNamed(Routes.detailsHistoryPayment).then((_) { Get.find<PaymentHistoryListController>().refreshList(); }); }, // 其他代码不变 )
方案3:通过路由参数传递 invoiceId(更优雅)
不在列表页注入 Controller,而是通过路由参数传递 invoiceId,在详情页的 Controller 中获取参数并初始化,避免实例复用问题:
1. 修改列表页跳转代码
InkWell( onTap: () { // 通过arguments传递invoiceId Get.toNamed(Routes.detailsHistoryPayment, arguments: payment.invoiceId!.toString()) .then((_) { Get.find<PaymentHistoryListController>().refreshList(); }); }, // 其他代码不变 )
2. 修改 DetailsPaymentHistoryController
class DetailsPaymentHistoryController extends GetxController with StateMixin<DetailsHistoryPaymentResponse> { final PaymentHistoryApi paymentHistoryApi; late String invoiceId; DetailsPaymentHistoryController({required this.paymentHistoryApi}); @override void onInit() { // 从路由参数中获取invoiceId invoiceId = Get.arguments as String; if (kDebugMode) { print('--------------------------'); print(invoiceId); } getPaymentHistoryDetails(); super.onInit(); } // 获取详情数据方法不变 void getPaymentHistoryDetails() async { change(null, status: RxStatus.loading()); try { await paymentHistoryApi .getPaymentHistoryDetails(invoiceId: invoiceId) .then((value) { var body = json.decode(value); change(DetailsHistoryPaymentResponse.fromJson(body), status: RxStatus.success()); if (kDebugMode) print(value); }).onError((error, stackTrace) { change(null, status: RxStatus.error(AppStrings.somthingWentWrong)); if (kDebugMode) print(error.toString()); }); } catch (error) { change(null, status: RxStatus.error(error.toString())); if (kDebugMode) print(error.toString()); } } }
3. 在详情页注入 Controller
在详情页的 build 方法中注入 Controller(确保每次进入页面都创建新实例):
class DetailsHistoryPaymentPage extends StatelessWidget { const DetailsHistoryPaymentPage({super.key}); @override Widget build(BuildContext context) { // 注入Controller,force: true确保每次进入都创建新实例 final controller = Get.put<DetailsPaymentHistoryController>( DetailsPaymentHistoryController(paymentHistoryApi: PaymentHistoryApi()), force: true, ); return Scaffold( // 页面内容... ); } }
列表页刷新说明
假设列表页使用 PaymentHistoryListController 管理数据,需要添加一个刷新方法:
class PaymentHistoryListController extends GetxController { final PaymentHistoryApi paymentHistoryApi; RxList<Payment> payments = RxList([]); PaymentHistoryListController({required this.paymentHistoryApi}); @override void onInit() { super.onInit(); fetchPayments(); } // 获取列表数据 void fetchPayments() async { // 调用接口获取列表并更新payments } // 刷新列表方法 void refreshList() { fetchPayments(); } }
内容的提问来源于stack exchange,提问作者Mehedi Hasan Sumon
相关产品推荐
相关产品推荐

