簡體   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