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
相关产品推荐
相关产品推荐

