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

静态布尔字段值未随其他类中条件正确变化的问题

静态布尔变量状态不一致问题排查与解决

问题描述

我编写了一个修改静态布尔变量的方法,希望根据该变量状态条件显示按钮组件:满足条件时设为true,否则设为false。方法内部打印变量值符合预期,但从其他类调用时,值却经常不符合预期——有时条件不满足仍显示true,满足时反而显示false。

相关代码

定义静态布尔变量的类

class GetBool {
  // 要修改的静态变量
  static bool? isAdded;
}

修改静态变量的方法

void getBool(String model) async {
    print("function ran");
    User? user = FirebaseAuth.instance.currentUser;
    DocumentSnapshot<Map<String, dynamic>> document = await FirebaseFirestore
        .instance
        .collection("Cart")
        .doc(user!.uid)
        .get();

    List list = [];
    for (var doc in document.data()!['cart'] as Iterable) {
      list.add(doc['model']);
      print("model says before condition $model");
      print("list is $list");

      if (list.contains(model)) {
        GetBool.isAdded = true;
        print("this item exist");
        print(GetBool.isAdded);
      } else {
        GetBool.isAdded = false;
        print("this item doesnt exist");
        print(GetBool.isAdded);
      }
    }
  }

调用方法的位置

class WatchTile extends StatefulWidget {
  final Watch? watch;
  const WatchTile({this.watch, super.key});

  @override
  State<WatchTile> createState() => _WatchTileState();
}

class _WatchTileState extends State<WatchTile> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.pushNamed(
          context,
          "/watch_details",
          arguments: widget.watch,
        );
        // 跳转时调用方法
        DatabaseService().getBool(widget.watch!.model!);
      },
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.black),
        ),
        child: Column(
          children: <Widget>[
            Container(
              height: 200,
              decoration: BoxDecoration(
                  image: DecorationImage(
                      image: NetworkImage(widget.watch!.image!),
                      fit: BoxFit.cover)),
            ),
            Container(
              padding: const EdgeInsets.only(left: 4.0),
              width: double.maxFinite,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    widget.watch!.brand!,
                    style: const TextStyle(color: Colors.grey),
                  ),
                  Text(widget.watch!.model!),
                  Text('\$${widget.watch!.price!}'),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

使用静态变量的页面

final FirebaseAuth auth = FirebaseAuth.instance;
User? user = auth.currentUser;

class WatchDetail extends StatefulWidget {
  const WatchDetail({super.key});

  @override
  State<WatchDetail> createState() => _WatchDetailState();
}

class _WatchDetailState extends State<WatchDetail> {
  final DatabaseService _database = DatabaseService();

  int itemQuantity = 1;
  @override
  Widget build(BuildContext context) {
    print("getbool says ${GetBool.isAdded}");

    final watch = ModalRoute.of(context)?.settings.arguments as Watch;
   

    print("route args is ${watch.brand}");
    return Scaffold(
      appBar: AppBar(
        title: Text(watch.brand!),
      ),
      body: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                // 根据静态变量条件显示按钮
                child: GetBool.isAdded == false
                    ? ElevatedButton(
                        style: ButtonStyle(),
                        onPressed: () async {
                          await _database.addToCart(watch.model!, watch.brand!,
                              itemQuantity, int.parse(watch.price!));
                        },
                        child: Text("Add To Cart"),
                      )
                    : ElevatedButton(
                        onPressed: () {}, child: Text("Added To Cart")),
              ),
              
            ],
          )
        ],
      ),
    );
  }
}

问题原因分析

  1. 异步时序错误:WatchTile的onTap中先执行页面跳转,再调用异步的getBool方法。跳转后WatchDetail的build会立即执行,此时getBool还未完成Firestore查询,GetBool.isAdded还是旧值或初始null,导致显示异常。
  2. 全局静态变量状态污染:静态变量是全局共享的,多个商品页面的异步操作会互相覆盖值。比如快速切换商品时,前一个请求的结果可能晚于新请求返回,覆盖正确状态。
  3. 循环逻辑错误:getBool中循环遍历购物车每个item,每次循环都会更新isAdded,最终状态由最后一个item的判断结果决定,而非整体购物车是否包含目标商品。

解决方案

1. 修复getBool方法逻辑

去掉冗余循环,直接判断购物车列表是否包含目标商品,同时改为返回Future<bool>,避免依赖全局静态变量:

Future<bool> getBool(String model) async {
  User? user = FirebaseAuth.instance.currentUser;
  if (user == null) return false;
  
  DocumentSnapshot<Map<String, dynamic>> document = await FirebaseFirestore
      .instance
      .collection("Cart")
      .doc(user.uid)
      .get();

  List cartItems = document.data()?['cart'] ?? [];
  // 直接判断是否存在目标商品
  bool isAdded = cartItems.any((item) => item['model'] == model);
  print("this item ${isAdded ? 'exist' : 'doesnt exist'}");
  return isAdded;
}

2. 调整页面跳转的异步时序

在WatchTile中等待getBool完成后,将结果作为参数传递给下一页:

onTap: () async {
  bool isAdded = await DatabaseService().getBool(widget.watch!.model!);
  Navigator.pushNamed(
    context,
    "/watch_details",
    arguments: {
      'watch': widget.watch,
      'isAdded': isAdded,
    },
  );
}

3. 在WatchDetail中本地维护状态

接收传递的参数,或者用FutureBuilder在页面内部获取状态,避免全局变量:

class _WatchDetailState extends State<WatchDetail> {
  final DatabaseService _database = DatabaseService();
  int itemQuantity = 1;

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)?.settings.arguments as Map;
    final Watch watch = args['watch'];
    final bool initialIsAdded = args['isAdded'];

    return Scaffold(
      appBar: AppBar(title: Text(watch.brand!)),
      body: Column(
        children: <Widget>[
          FutureBuilder<bool>(
            future: _database.getBool(watch.model!),
            initialData: initialIsAdded,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              }
              bool isAdded = snapshot.data ?? false;
              return ElevatedButton(
                onPressed: isAdded ? null : () async {
                  await _database.addToCart(
                    watch.model!, 
                    watch.brand!,
                    itemQuantity, 
                    int.parse(watch.price!)
                  );
                  // 添加后刷新状态
                  setState(() {});
                },
                child: Text(isAdded ? "Added To Cart" : "Add To Cart"),
              );
            },
          ),
        ],
      ),
    );
  }
}

注意事项

  • 避免用全局静态变量管理页面状态,异步场景下极易引发状态混乱。
  • 页面状态尽量由自身维护,或使用Provider、Riverpod等专门的状态管理工具。
  • 异步操作必须保证时序正确,确保数据准备完成后再更新UI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:09