You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 13:31:01