【问题标题】:How do I show a snackbar from a StateNotifier in Riverpod?如何在 Riverpod 中显示来自 StateNotifier 的小吃店?
【发布时间】:2021-05-24 18:44:07
【问题描述】:

我的以下课程运行良好。

class CartRiverpod extends StateNotifier<List<CartItemModel>> {

    CartRiverpod([List<CartItemModel> products]) : super(products ?? []);

        void add(ProductModel addProduct) {
            bool productExists = false;
                for (final product in state) {
                    if (product.id == addProduct.id) {
                        print("not added");
                        productExists = true;
                    }
                    else {
                    }
                 }
        if (productExists==false)
            {
                state = [
                    ...state, new CartItemModel(product: addProduct),
                ];
                print("added");
             }

    }

    void remove(String id) {
      state = state.where((product) => product.id != id).toList();
    }
  }

上面的代码完美运行。在我的购物车中,我想将产品的订单限制为 1 个单位,这就是我执行上面代码的原因。它按我的预期工作。 现在唯一的事情是,我想显示一个快餐栏,提醒用户他或她只能订购每种产品的 1 个单位。

如何在我的 StateNotifier 中添加一个快餐栏?

【问题讨论】:

    标签: flutter dart snackbar riverpod


    【解决方案1】:
    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/all.dart';
    import 'package:freezed_annotation/freezed_annotation.dart';
    part 'cart_list_page.freezed.dart';
    
    final cartListPageStateNotifierProvider =
        StateNotifierProvider((ref) => CartListPageStateNotifier(ref.read));
    
    final cartListProvider = StateProvider((ref) {
      return <CartListItemModel>[];
    }); // this holds the cart list, at initial, its empty
    
    class CartListPage extends StatefulWidget {
      @override
      _CartListPageState createState() => _CartListPageState();
    }
    
    class _CartListPageState extends State<CartListPage> {
      final _scaffoldKey = GlobalKey<ScaffoldState>();
      List<CartListItemModel> productsToBeAddedToCart = [
        CartListItemModel(id: 1, name: "Apple"),
        CartListItemModel(id: 2, name: "Tomatoes"),
        CartListItemModel(id: 3, name: "Oranges"),
        CartListItemModel(id: 4, name: "Ginger"),
        CartListItemModel(id: 5, name: "Garlic"),
        CartListItemModel(id: 6, name: "Pine"),
      ];
    
      @override
      Widget build(BuildContext context) {
        return ProviderListener<CartListState>(
          provider: cartListPageStateNotifierProvider.state,
          onChange: (context, state) {
            return state.maybeWhen(
              loading: () {
                final snackBar = SnackBar(
                  duration: Duration(seconds: 2),
                  backgroundColor: Colors.yellow,
                  content: Text('updating cart....'),
                );
                return _scaffoldKey.currentState.showSnackBar(snackBar);
              },
              success: (info) {
                final snackBar = SnackBar(
                  duration: Duration(seconds: 2),
                  backgroundColor: Colors.green,
                  content: Text('$info'),
                );
                _scaffoldKey.currentState.hideCurrentSnackBar();
                return _scaffoldKey.currentState.showSnackBar(snackBar);
              },
              error: (errMsg) {
                final snackBar = SnackBar(
                  duration: Duration(seconds: 2),
                  backgroundColor: Colors.red,
                  content: Text('$errMsg'),
                );
                _scaffoldKey.currentState.hideCurrentSnackBar();
                return _scaffoldKey.currentState.showSnackBar(snackBar);
              },
              orElse: () => SizedBox.shrink(),
            );
          },
          child: Scaffold(
            key: _scaffoldKey,
            body: Container(
              height: MediaQuery.of(context).size.height,
              width: MediaQuery.of(context).size.width,
              child: Column(
                children: [
                  SizedBox(height: 40),
                  Expanded(
                    child: ListView.builder(
                      itemCount: productsToBeAddedToCart.length,
                      itemBuilder: (context, index) {
                        final item = productsToBeAddedToCart[index];
                        return ListTile(
                          title: Text("${item.name}"),
                          leading: CircleAvatar(child: Text("${item.id}")),
                          trailing: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              IconButton(
                                icon: Icon(Icons.add),
                                onPressed: () => context
                                    .read(cartListPageStateNotifierProvider)
                                    .addProduct(item),
                              ),
                              SizedBox(width: 2),
                              IconButton(
                                icon: Icon(Icons.remove),
                                onPressed: () => context
                                    .read(cartListPageStateNotifierProvider)
                                    .removeProduct(item),
                              ),
                            ],
                          ),
                        );
                      },
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class CartListPageStateNotifier extends StateNotifier<CartListState> {
      final Reader reader;
      CartListPageStateNotifier(this.reader) : super(CartListState.initial());
    
      addProduct(CartListItemModel product) async {
        state = CartListState.loading();
        await Future.delayed(Duration(seconds: 1));
        var products = reader(cartListProvider).state;
        if (!products.contains(product)) {
          reader(cartListProvider).state.add(product);
          return state =
              CartListState.success("Added Successfully ${product.name}");
        } else {
          return state = CartListState.error(
              "cannot add more than 1 product of the same kind");
        }
      }
    
      removeProduct(CartListItemModel product) async {
        state = CartListState.loading();
        await Future.delayed(Duration(seconds: 1));
        var products = reader(cartListProvider).state;
        if (products.isNotEmpty) {
          bool status = reader(cartListProvider).state.remove(product);
          if (status) {
            return state =
                CartListState.success("removed Successfully ${product.name}");
          } else {
            return state;
          }
        }
        return state = CartListState.error("cart is empty");
      }
    }
    
    @freezed
    abstract class CartListState with _$CartListState {
      const factory CartListState.initial() = _CartListInitial;
      const factory CartListState.loading() = _CartListLoading;
      const factory CartListState.success([String message]) = _CartListSuccess;
      const factory CartListState.error([String message]) = _CartListError;
    }
    
    @freezed
    abstract class CartListItemModel with _$CartListItemModel {
      factory CartListItemModel({final String name, final int id}) =
          _CartListItemModel;
    }
    

    【讨论】:

    • 对不起,我有点过火了。要运行此代码,您需要 build_runner,因为我使用了 freezed。安装:冻结的 build_runner 命令:flutter pub run build_runner build
    • ProviderListener 已被弃用,ref.listen 现在是根据 Riverpod 的文档在发生错误时显示快餐栏的推荐方式。
    【解决方案2】:

    不要在此处显示小吃店。 您需要在小部件树中侦听所需的值,如下所示:

    @override
      Widget build(BuildContext context, WidgetRef ref) {
        ref.listen(cartListPageStateNotifierProvider, (value) {
          // show snackbar here...
        });
        ...
      }
    

    【讨论】:

      猜你喜欢
      • 2022-10-08
      • 2020-05-18
      • 2022-12-17
      • 2016-04-01
      • 1970-01-01
      • 2018-05-04
      • 2021-06-03
      • 2020-05-22
      • 2020-04-07
      相关资源
      最近更新 更多