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

Bloc发送列表状态后UI未更新,热重载才生效问题求助

问题分析与解决方案

你遇到的核心问题是:修改的是原状态列表的引用,导致Bloc无法检测到状态变化,UI不刷新。热重载后UI更新是因为热重载会重建Widget,强制读取当前状态的列表值。

原代码的问题

你通过state.copyWith().listSelectedTest获取的列表,本质上还是原状态里的列表引用(因为copyWith在未传参时会直接复用原列表)。直接对这个列表做add/remove操作,属于修改原状态的可变对象;后续emit的新状态中,listSelectedTest和原状态的列表是同一个引用,Bloc的默认浅比较会认为状态没有变化,因此不会触发UI刷新。

修正后的代码

void _onChangeTest(OnPriceChangeTest event, var emit) {
  final state = this.state;
  if (state is PriceChangeTest) {
    try {
      // 直接从原状态拿列表,并创建全新副本,避免修改原状态
      List<String> listSelectedTest = List.from(state.listSelectedTest ?? []);
      printlog("price change test-1", "$listSelectedTest");
      
      if (event.selected) {
        listSelectedTest.remove(event.value);
      } else {
        listSelectedTest.add(event.value);
      }
      
      printlog("price change test-2", listSelectedTest.toString());
      // 传入新列表副本,生成全新状态
      emit(
        state.copyWith(
          listSelectedTest: listSelectedTest,
        ),
      );
    } catch (e) {
      printlog("price change test", e.toString());
    }
  }
}

额外注意事项

如果你的PriceChangeTest类是自定义的(非freezed等代码生成工具生成),需要确保==和hashCode方法正确比较列表内容而非引用:

import 'package:flutter/foundation.dart';

class PriceChangeTest {
  final List<String>? listSelectedTest;

  PriceChangeTest({this.listSelectedTest});

  PriceChangeTest copyWith({
    List<String>? listSelectedTest,
  }) {
    return PriceChangeTest(
      listSelectedTest: listSelectedTest ?? this.listSelectedTest,
    );
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is PriceChangeTest &&
          runtimeType == other.runtimeType &&
          listEquals(listSelectedTest, other.listSelectedTest);

  @override
  int get hashCode => listSelectedTest.hashCode;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:01:24