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

从子视图返回后如何更新Flutter AppBar中的值?

问题分析与解决方案

核心问题

你遇到的问题本质有两点:

  1. 局部变量被重置:amount是build方法内的局部变量,每次组件重建(包括setState触发的重建)都会重新从widget.jobObject.totalAmount赋值,你在setState里修改的只是临时变量,下次build就会被覆盖。
  2. 传入的Job对象未更新:widget.jobObject是页面初始化时传入的旧数据,添加交易后后端的Job总额已更新,但前端这个对象没有同步刷新,始终保留初始值。

解决方案(两种可选)

方案一:通过交易列表计算总额(推荐)

既然你已经在监听该作业的交易列表,直接从交易数据中累加计算总额即可,无需依赖传入的Job对象。这样交易列表更新时,总额会自动同步:

class _TxnsByJobState extends ConsumerState<TxnsByJob> {
  @override
  Widget build(BuildContext context) {
    final jobTxnsListValue =
        ref.watch(transactionsListForJobProvider(widget.jobObject.id!));

    // 计算总额:有交易数据则累加,无数据时用初始值兜底
    num amount = widget.jobObject.totalAmount;
    if (jobTxnsListValue.hasValue && jobTxnsListValue.value != null) {
      amount = jobTxnsListValue.value!.fold(
        0,
        (sum, txn) => sum + txn.amount,
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: StyledHeadline(widget.jobObject.name),
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(12.0),
          child: StyledNumberText(
            FbFormatter.formatCurrency(amount.toDouble()),
            amount >= 0 ? AppColors.greenColor : AppColors.redColor,
          ),
        ),
      ),
      body: jobTxnsListValue.when(
        data: (txns) => ListView.builder(
          itemCount: txns.length,
          itemBuilder: (context, index) {
            return FbTile(
                title: txns[index].payee.name,
                subtitle: txns[index].date,
                amount: txns[index].amount as double,
                note: txns[index].costcode.name,
                category: txns[index].costcode.category);
          },
        ),
        error: (e, st) => Center(child: Text('Error! $e')),
        loading: () =>
            const Center(child: CircularProgressIndicator.adaptive()),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await Navigator.of(context).push(
            MaterialPageRoute(
              fullscreenDialog: true,
              builder: (context) => AddTransactionTest(job: widget.jobObject),
            ),
          );
          // 仅需失效交易列表provider,总额会随交易数据自动计算更新
          ref.invalidate(transactionsListForJobProvider(widget.jobObject.id!));
        },
        child: const Icon(Icons.add, size: 36),
      ),
    );
  }
}

方案二:为Job对象单独创建Provider

如果需要严格同步后端的Job对象数据,可以为单个Job创建Provider,更新交易后重新拉取最新的Job数据:

  1. 先定义Job的Provider:
final jobProvider = FutureProvider.family<FbJob, String>((ref, jobId) async {
  // 从Supabase拉取最新的Job对象
  final response = await supabase.from('jobs').select().eq('id', jobId).single();
  return FbJob.fromJson(response);
});
  1. 修改页面代码:
class _TxnsByJobState extends ConsumerState<TxnsByJob> {
  @override
  Widget build(BuildContext context) {
    final jobValue = ref.watch(jobProvider(widget.jobObject.id!));

    return jobValue.when(
      data: (job) {
        final jobTxnsListValue = ref.watch(transactionsListForJobProvider(job.id!));
        return Scaffold(
          appBar: AppBar(
            title: StyledHeadline(job.name),
            bottom: PreferredSize(
              preferredSize: const Size.fromHeight(12.0),
              child: StyledNumberText(
                FbFormatter.formatCurrency(job.totalAmount.toDouble()),
                job.totalAmount >= 0 ? AppColors.greenColor : AppColors.redColor,
              ),
            ),
          ),
          body: jobTxnsListValue.when(
            data: (txns) => ListView.builder(
              itemCount: txns.length,
              itemBuilder: (context, index) {
                return FbTile(
                    title: txns[index].payee.name,
                    subtitle: txns[index].date,
                    amount: txns[index].amount as double,
                    note: txns[index].costcode.name,
                    category: txns[index].costcode.category);
              },
            ),
            error: (e, st) => Center(child: Text('Error! $e')),
            loading: () =>
                const Center(child: CircularProgressIndicator.adaptive()),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () async {
              await Navigator.of(context).push(
                MaterialPageRoute(
                  fullscreenDialog: true,
                  builder: (context) => AddTransactionTest(job: job),
                ),
              );
              // 同时失效Job和交易列表的Provider,拉取最新数据
              ref.invalidate(jobProvider(job.id!));
              ref.invalidate(transactionsListForJobProvider(job.id!));
            },
            child: const Icon(Icons.add, size: 36),
          ),
        );
      },
      error: (e, st) => Center(child: Text('Error! $e')),
      loading: () => const Center(child: CircularProgressIndicator.adaptive()),
    );
  }
}

内容的提问来源于stack exchange,提问作者Andy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:46:15