繁体   English   中英

Flutter_bloc:^8.0.0 State 在使用不同的道具发出相同的 state 时不会重建

[英]Flutter_bloc: ^8.0.0 State does not rebuild when emitting the same state with different props

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

我的原型有 3 个屏幕:

  1. 列表视图( https://i.stack.imgur.com/bI9K6.png
  2. 列表项的详细信息页面( https://i.stack.imgur.com/DByDn.png
  3. 表格( https://i.stack.imgur.com/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];
}

最重要的部分是在更改下一页上的表单时设置星星不能解决问题。 奇怪的是它会改变,如果我在发出 state 之前发出另一个 state 我希望应用程序进入。

我希望这对大家有意义。 这是我在 StackOverflow 上的第一篇文章,因此我将不胜感激!

我找到了问题!

我过早地设置了我的项目属性,这导致 BLoC 无法识别更改,因为它是正在设置的同一产品。

因此,不要在 onChange 事件中设置 item.xx,而是尝试将结果存储在另一个地方,例如 TextEditingController。 然后在提交表单时,使用存储的数据创建一个新的 object,这将被识别为更改。

BlocLibrary 常见问题解答

如果您使用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM