[英]Flutter_bloc: ^8.0.0 State does not rebuild when emitting the same state with different props
我正在试验 state 管理原型,最近偶然发现了一个问题。 问题是一个交互确实会重新加载屏幕,这很好。 虽然另一个交互不会重新加载屏幕,即使它发出相同的 state(也具有更改的道具)。
我的原型有 3 个屏幕:
屏幕截图中的星星在下面的小部件中表示:
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];
}
最重要的部分是在更改下一页上的表单时设置星星并不能解决问题。 奇怪的是它会改变,如果我在发出 state 之前发出另一个 state 我希望应用程序进入。
我希望这对大家有意义。 这是我在 StackOverflow 上的第一篇文章,因此我将不胜感激!
我找到了问题!
我过早地设置了我的项目属性,这导致 BLoC 无法识别更改,因为它是正在设置的同一产品。
因此,不要在 onChange 事件中设置 item.xx,而是尝试将结果存储在另一个地方,例如 TextEditingController。 然后在提交表单时,使用存储的数据创建一个新的 object,这将被识别为更改。
如果您使用 Equatable,请确保将所有属性传递给 props getter。
abstract class MyState extends Equatable {
const MyState();
}
class StateA extends MyState {
final String property;
const StateA(this.property);
@override
List<Object> get props => [property]; // pass all properties to props
}
它对我有用,希望对你也有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.