Flutter_bloc : ^8. 0.0 状态在使用不同 Prop 发出相同状态时不会重建

标签 flutter bloc state-management

我正在试验状态管理原型(prototype),最近偶然发现了一个问题。问题是一次交互确实会重新加载屏幕,这很好。虽然另一个交互不会重新加载屏幕,即使它发出相同的状态(也使用更改的 prop)。

我的原型(prototype)有 3 个屏幕:

  1. ListView ( /image/bI9K6.png )
  2. 列表项的详细信息页面 ( /image/DByDn.png )
  3. 表格 ( /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/

相关文章:

dart - 如何检查对象是否属于实例 `Type` ?

c++ - 通过 Flutter 从 C++ 插件访问资源

javascript - React 上下文初始状态正在发生变化 - JavaScript/React

testing - Flutter:如何模拟 Bloc

android - Flutter:当我可以使用全局变量并改用 setState 时,状态管理库需要什么?

ajax - 在 URL Hash/Fragment 中存储 JSON 的最佳实践

ios - 尝试为 iOS 构建 flutter 应用程序时出现问题

flutter - Flutter 中 After Effects 文件的使用

flutter - 如何多次触发具有相同状态的 block 监听器?

flutter - 如果我的 Bloc 的状态是一个小部件列表,这是一种不好的做法吗?