我正在试验状态管理原型(prototype),最近偶然发现了一个问题。问题是一次交互确实会重新加载屏幕,这很好。虽然另一个交互不会重新加载屏幕,即使它发出相同的状态(也使用更改的 prop)。
我的原型(prototype)有 3 个屏幕:
- ListView ( /image/bI9K6.png )
- 列表项的详细信息页面 ( /image/DByDn.png )
- 表格 ( /image/s8ltv.png )
屏幕截图中的星星在下面的小部件中表示:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:state_management/models/product/product.dart';
import 'package:state_management/models/product/product_bloc.dart';
class RatingBox extends StatefulWidget {
final Product item;
RatingBox({
Key ? key, required this.item
}): super(key: key);@
override
_RatingBoxState createState() {
return _RatingBoxState();
}
}
class _RatingBoxState extends State < RatingBox > {@
override
Widget build(BuildContext context) {
double _size = 20;
return Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
for (int i = 1; i <= 3; i++)
Container(
padding: const EdgeInsets.all(0),
child: IconButton(
icon: (widget.item.rating >= i ? Icon(
Icons.star,
size: _size,
) : Icon(
Icons.star_border,
size: _size,
)),
color: Colors.red[500],
onPressed: () {
context.read < ProductBloc > ().add(UpdateProductRating(
product: widget.item.copyWith(rating: i)));
},
iconSize: _size,
),
),
],
);
}
}
表单通过提交按钮更新,使用另一个事件(出于测试目的)。但它内部有相同的代码:
context.read < ProductBloc > ().add(UpdateProduct(
product: item.copyWith(
name: item.name,
description: item.description,
price: item.price)));
下面的代码是product_bloc、product_event和product_state的代码:
class ProductBloc extends Bloc < ProductEvent, ProductState > {
ProductBloc(): super(ProductLoading()) {
on < LoadProduct > (_onLoadProduct);
on < UpdateProduct > (_onUpdateProduct);
on < UpdateProductRating > (_onUpdateProductRating);
}
void _onLoadProduct(LoadProduct event, Emitter < ProductState > emit) {
print('load');
emit(
ProductLoaded(products: event.products),
);
}
void _onUpdateProductRating(
UpdateProductRating event, Emitter < ProductState > emit) {
final state = this.state;
if (state is ProductLoaded) {
print('updateRating');
List < Product > products = (state.products.map((product) {
return product.id == event.product.id ? event.product : product;
})).toList();
emit(ProductLoaded(products: List.of(products)));
}
}
void _onUpdateProduct(UpdateProduct event, Emitter < ProductState > emit) {
final state = this.state;
if (state is ProductLoaded) {
print('update');
List < Product > products = (state.products.map((product) {
return product.id == event.product.id ? event.product : product;
})).toList();
emit(ProductLoaded(products: products));
}
}
}
abstract class ProductEvent extends Equatable {
const ProductEvent();@
override
List < Object > get props = > [];
}
class LoadProduct extends ProductEvent {
final List < Product > products;
const LoadProduct({
this.products = const < Product > []
});@
override
List < Object > get props = > [products];
}
class UpdateProduct extends ProductEvent {
final Product product;
const UpdateProduct({
required this.product
});@
override
List < Object > get props = > [product];
}
class UpdateProductRating extends ProductEvent {
final Product product;
const UpdateProductRating({
required this.product
});@
override
List < Object > get props = > [product];
}
abstract class ProductState extends Equatable {
const ProductState();@
override
List < Object > get props = > [];
}
class ProductLoading extends ProductState {}
class ProductLoaded extends ProductState {
final List < Product > products;
const ProductLoaded({
this.products = const < Product > []
});@
override
List < Object > get props = > [products];
}
最重要的部分是设置星标会而更改下一页的表单不会达到目的。奇怪的是,如果我在发出我希望应用程序所处的状态之前发出另一个状态,它会发生变化。
我希望这对大家有意义。这是我在 StackOverflow 上的第一篇文章,非常感谢您的反馈!
最佳答案
我找到问题了!
我过早地设置了我的项目属性,这导致 BLoC 无法识别更改,因为它是正在设置的同一产品。
因此,不要在 onChange 事件中设置 item.xx,而是尝试将结果存储在另一个地方,例如 TextEditingController。然后在提交表单时,使用存储的数据创建一个新对象,该对象将被识别为更改。
关于Flutter_bloc : ^8. 0.0 状态在使用不同 Prop 发出相同状态时不会重建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71112458/