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

Flutter:如何用stacked包实现Future列表刷新后显示小计

使用Stacked实现该场景的最佳方案

完全不需要为小计单独创建ViewModel,直接在现有的FutureViewModel里处理即可——毕竟小计是商品列表的衍生数据,放在同一个ViewModel中维护逻辑更连贯。以下是具体实现步骤和代码示例:

1. 编写ViewModel逻辑

核心思路是在ViewModel中维护选中日期、商品列表,同时通过计算属性或方法自动生成小计,利用Stacked的响应式能力通知UI更新:

import 'package:stacked/stacked.dart';
import 'package:your_app/models/product.dart';
import 'package:your_app/services/product_service.dart';

class ProductListViewModel extends FutureViewModel<List<Product>> {
  final ProductService _productService = ProductService();
  DateTime _selectedDate = DateTime.now();
  
  // 用@observable标记,让Stacked感知变量变化
  @observable
  List<Product> _products = [];

  DateTime get selectedDate => _selectedDate;

  // 用@computed自动计算小计,每次_products变化时自动更新
  @computed
  double get subtotal => _products.fold(
    0.0,
    (total, product) => total + product.price,
  );

  // 日期变更时重新获取数据
  void updateDate(DateTime newDate) {
    _selectedDate = newDate;
    // 重新触发Future获取新数据
    setFuture(_fetchProductsByDate());
  }

  @override
  Future<List<Product>> futureToRun() => _fetchProductsByDate();

  Future<List<Product>> _fetchProductsByDate() async {
    final fetchedProducts = await _productService.getProducts(_selectedDate);
    _products = fetchedProducts;
    return fetchedProducts;
  }
}

2. 实现UI层

通过ViewModelBuilder绑定ViewModel,在AppBar中直接读取subtotal,日期选择器触发updateDate方法即可:

import 'package:flutter/material.dart';
import 'package:stacked/stacked.dart';
import 'package:your_app/viewmodels/product_list_viewmodel.dart';
import 'package:your_app/models/product.dart';

class ProductListView extends StatelessWidget {
  const ProductListView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ViewModelBuilder<ProductListViewModel>.reactive(
      viewModelBuilder: () => ProductListViewModel(),
      onModelReady: (model) => model.fetchData(),
      builder: (context, model, child) {
        return Scaffold(
          appBar: AppBar(
            title: const Text("商品列表"),
            actions: [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 16),
                child: Text(
                  "小计: ¥${model.subtotal.toStringAsFixed(2)}",
                  style: const TextStyle(fontSize: 16),
                ),
              ),
            ],
          ),
          body: model.isBusy
              ? const Center(child: CircularProgressIndicator())
              : Column(
                  children: [
                    // 日期选择按钮
                    ElevatedButton(
                      onPressed: () async {
                        final pickedDate = await showDatePicker(
                          context: context,
                          initialDate: model.selectedDate,
                          firstDate: DateTime(2020),
                          lastDate: DateTime.now(),
                        );
                        if (pickedDate != null) {
                          model.updateDate(pickedDate);
                        }
                      },
                      child: Text("选择日期: ${model.selectedDate.toString().split(' ')[0]}"),
                    ),
                    // 商品列表
                    Expanded(
                      child: ListView.builder(
                        itemCount: model.data?.length ?? 0,
                        itemBuilder: (context, index) {
                          final product = model.data![index];
                          return ListTile(
                            title: Text(product.name),
                            trailing: Text("¥${product.price.toStringAsFixed(2)}"),
                          );
                        },
                      ),
                    ),
                  ],
                ),
        );
      },
    );
  }
}

关键说明

  • 利用@observable和@computed实现响应式:商品列表更新时,小计会自动重新计算,UI也会同步刷新
  • 无需额外ViewModel:小计属于商品列表的附属数据,放在同一个ViewModel中能避免状态分散,逻辑更清晰
  • 复用FutureViewModel的状态管理:直接用setFuture重新触发数据请求,自动处理加载、错误等状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:15:42