我试图在创建对象后更新状态。 我已经使用
freezed
包创建了 ObjectsState,因此没有必要使用 Equatable,因为它已经由包添加了。
class ObjectsState with _$ObjectsState {
const factory ObjectsState.initial() = Initial;
const factory ObjectsState.loading() = _Loading;
const factory ObjectsState.loaded(ObjectsListResponse response) = Loaded;
const factory ObjectsState.error(String message) = _Error;
}
那么,这是我的获取对象事件
@freezed
class ObjectsEvent with _$ObjectsEvent {
const factory ObjectsEvent.onFetchObjects() = _OnFetchObjects;
}
但我也有单独的
CreateObjectEvent
。
还有我的块文件:
class ObjectsBloc extends Bloc<ObjectsEvent, ObjectsState> {
final ObjectsUseCase objectsUseCase;
ObjectsBloc({required this.objectsUseCase})
: super(const ObjectsState.initial()) {
on<ObjectsEvent>((event, emit) => event.when(
onFetchObjects: () => _fetchObjects(emit),
));
}
Future<void> _fetchObjects(Emitter<ObjectsState> emit) async {
emit(const ObjectsState.loading());
try {
final response = await objectsUseCase.executeFetchObjects();
if (response.isError || response.result == null) {
emit(ObjectsState.error(
response.errorMessage ?? 'Failed to fetch objects'));
} else {
final updatedResponse = response.result!.copyWith(
objectsList: List.from(response.result!.objectsList),
total: response.result!.total,
);
final loadedState = ObjectsState.loaded(updatedResponse);
final updatedState = (loadedState as Loaded).copyWith(
response: updatedResponse,
);
emit(updatedState);
}
} catch (e) {
emit(ObjectsState.error(e.toString()));
}
}
}
所以,在舞台上
emit(updatedState);
updatedState 具有正确的值,但是当它进入 UI 部分时 - 没有任何更新
class ObjectsScreenWrapper extends StatefulWidget {
ObjectsScreenWrapper({super.key});
@override
State<ObjectsScreenWrapper> createState() => _ObjectsScreenWrapperState();
}
class _ObjectsScreenWrapperState extends State<ObjectsScreenWrapper> {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ObjectsBloc>(
create: (_) =>
ObjectsBloc(
objectsUseCase: GetIt.I<ObjectsUseCase>(),
),
),
BlocProvider<BalanceBloc>(
create: (_) =>
BalanceBloc(
balanceUseCase: GetIt.I<BalanceUseCase>(),
),
),
],
child: ObjectsScreen(),
);
}
}
class ObjectsScreen extends StatelessWidget {
ObjectsScreen({super.key});
@override
Widget build(BuildContext context) {
if (context.read<ObjectsBloc>().state is Initial) {
context.read<ObjectsBloc>().add(const ObjectsEvent.onFetchObjects());
}
BlocBuilder<ObjectsBloc, ObjectsState>(
key: ValueKey(context.watch<ObjectsBloc>().state),
builder: (context, state) {
return state.when(
initial: ...
loading: ...
loaded: (objectsListResponse) {
if (objectsListResponse.total <= 0) {
return ... ;
} else {
return ObjectsLayoutGrid(
key: ValueKey(objectsListResponse
.copyWith()
.objectsList
.hashCode),
我发现了很多相关问题,但没有任何对我有用。如果有人知道如何解决这个问题,请帮忙
据我所知,当我们与 Freezed 发出相同的状态时,UI 不会重建,因为 Freezed 会比较状态并在它们相等时跳过重建,因此为了确保 UI 重建,您可以添加一个更改的字段每个发出的时间戳如下:
修改您的状态
将 DateTime 或 int 像下面的字段添加到您的状态:
const factory ObjectsState.loaded(
ObjectsListResponse response,
{required DateTime updatedAt}
) = Loaded;
发出更新状态
发出新状态时,请包含更新的时间戳:
emit(ObjectsState.loaded(
updatedResponse,
updatedAt: DateTime.now(),
));