简体   繁体   中英

Flutter UI update with Riverpod StateNotifierProvider

I want to make a checkbox form in Flutter and I'm using Riverpod to do it. I just started learning Riverpod and Flutter . The problem is when i check the checkbox it's update the state but checkbox is not updating/not checking.

And i want to add .autoDispose to provider to when user leave the page the form have to reset. But i guess .autoDispose working only FutureProvider and StreamProvider ?

Here is my code:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:neshapp/utils/constants.dart';
import '../../providers/MenuProviders.dart';

class MenuViewSingleItemPage extends ConsumerWidget {
  const MenuViewSingleItemPage({Key? key, required this.menu, required this.selectedProductId, required this.productIndex}) : super(key: key);

  final menu;
  final String selectedProductId;
  final int productIndex;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final categoryIndex = ref.watch(categoryIndexProvider);

    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            "${menu[categoryIndex]['category_products'][productIndex]['product_name']}",
            style: TextStyle(color: constsColor.black, fontSize: 15),
          ),
          titleSpacing: 0,
          backgroundColor: Colors.transparent,
          elevation: 0,
          leading: BackButton(
            color: constsColor.black,
          ),
        ),
        body: MenuViewSingleItemPageBody(
          product: menu[categoryIndex]['category_products'][productIndex],
        ),
      ),
    );
  }
}

class MenuViewSingleItemPageBody extends ConsumerWidget {
  const MenuViewSingleItemPageBody({Key? key, required this.product}) : super(key: key);

  final product;



  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Container(
      padding: EdgeInsets.all(12),
      child: ListView.builder(
        itemCount: product['product_options'].length,
        itemBuilder: (BuildContext context, index) {
          final options = product['product_options'];

          ref.watch(menuOptionsResultProvider.notifier).setOptions(options);

          return Container(
            child: Column(
              children: [
                SizedBox(
                  height: 16,
                ),
                Align(
                  alignment: Alignment.centerLeft,
                  child: Text(
                    "${options[index]['product_options_name']}",
                    style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                SizedBox(
                  height: 16,
                ),
                MenuViewSingleItemPageOptionBuilder(
                  options: options,
                  getterIndex: index,
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

final menuOptionsResultProvider = StateNotifierProvider<MenuOptionsResult, List<dynamic>>((ref) {
  return MenuOptionsResult();
});

class MenuOptionsResult extends StateNotifier<List<dynamic>> {
  MenuOptionsResult() : super([]);

  void setOptions(options) {
    state = options;
  }

  void updateOption(getterIndex, index, value) {

    state[getterIndex]["product_options_content"][index]['isSelected'] = value;
    state = state;
  }

}

class MenuViewSingleItemPageOptionBuilder extends ConsumerWidget {
  const MenuViewSingleItemPageOptionBuilder({Key? key, required this.options, required this.getterIndex}) : super(key: key);

  final int getterIndex;
  final List options;

  @override
  Widget build(BuildContext context, WidgetRef ref) {

    final providerOptions = ref.watch(menuOptionsResultProvider);

    return ListView.builder(
      shrinkWrap: true,
      itemCount: providerOptions[getterIndex]["product_options_content"].length,
      itemBuilder: (BuildContext context, index) {

        final optionsContent = providerOptions[getterIndex]["product_options_content"];
        final optionName = optionsContent[index]['product_options_content_name'];
        final optionPrice = optionsContent[index]['product_options_price'] != 0 ? "+ ${optionsContent[index]['product_options_price'].toStringAsFixed(2)}" : '';
        final optionsIsSelected = optionsContent[index]['isSelected'];
        final productOptionsContentId = optionsContent[index]['product_options_content_id'];

        return Container(
          child: Column(
            children: [
              CheckboxListTile(
                controlAffinity: ListTileControlAffinity.leading,
                title: Text(optionName.toString()),
                secondary: Text(optionPrice.toString()),
                value: optionsIsSelected,
                onChanged: (value) {
                  ref.watch(menuOptionsResultProvider.notifier).updateOption(getterIndex, index, value);
                },
                activeColor: Colors.red,
                checkColor: Colors.white,
              ),
              SizedBox(
                height: 14,
              ),
            ],
          ),
        );
      },
    );
  }
}

And menu data is like that:

[
   {
      "category_name":"Burger",
      "category_id":hL07pON2cSH057NrvNZG,
      "category_products":[
         {
            "product_discount_price":51,
            "product_options":[
               {
                  "product_options_name":"Soslar",
                  "product_options_content":[
                     {
                        "product_options_price":5.5,
                        "isSelected":false,
                        "product_options_content_id":3LHTHip4Vw5JtHZA7vo5,
                        "product_options_content_name":"Ketçap"
                     },
                     {
                        "product_options_price":0,
                        "isSelected":false,
                        "product_options_content_id":UwNDGkPIZ9322D8vXyk8,
                        "product_options_content_name":"Mayonez"
                     },
                     {
                        "product_options_price":2,
                        "isSelected":false,
                        "product_options_content_id":yrlf7LZSBqv1SXdjPQrV,
                        "product_options_content_name":"Barbekü Sos"
                     }
                  ]
               },
               {
                  "product_options_content":[
                     {
                        "product_options_price":0,
                        "isSelected":false,
                        "product_options_content_id":gBIJXEfuW1F54vFgOWCV,
                        "product_options_content_name":"Marul"
                     },
                     {
                        "product_options_price":3.45,
                        "isSelected":true,
                        "product_options_content_id":oSFB3vv0AMyDCX4aVI1H,
                        "product_options_content_name":"Turşu"
                     }
                  ],
                  "product_options_name":"Soğuklar"
               }
            ],
            "product_image":"http......",
            "product_id":8gJGzSzbsHTICTKTQw1g,
            "product_price":58,
            "product_description":"Lorem ipsum dolor sit amet",
            "consectetur adipiscing elit. Nulla est sem",
            "sagittis eget venenatis vitae",
            "faucibus id lacus. Nulla facilisi. Morbi risus augue",
            "lacinia a nibh eu",
            "ultrices maximus nulla.",
            "product_name":"Gurme Burger"
         },
         {
            "product_discount_price":0,
            "product_image":"http......,
            "product_id":CQ72e35kcl1vdNjAXGp0,
            "product_price":65,
            "product_description":"Donec posuere",
            "eros ut volutpat aliquam",
            "lacus libero aliquam odio",
            "a pellentesque risus nunc vitae elit. Nullam consectetur gravida erat",
            "sit amet hendrerit erat faucibus at. Praesent dolor magna",
            "mattis condimentum mi non",
            "condimentum dictum velit. Sed nibh lorem",
            "fermentum eu feugiat at",
            "porta at felis.",
            "product_name":"BBQ Burger"
         },
         {
            "product_discount_price":0,
            "product_image":"http......",
            "product_id":IWNSV2CQhqLKmu61Adxi,
            "product_price":68,
            "product_description":"Donec mi nulla",
            "auctor in urna et",
            "porta imperdiet quam. Nam in ligula ultricies orci porta facilisis. Nulla facilisi. Aenean quis lacinia mi",
            "ut imperdiet eros. Suspendisse suscipit hendrerit odio sed pulvinar.",
            "product_name":"Mexicano Burger"
         },
         {
            "product_discount_price":55,
            "product_image":"http":,
            "product_id":E1MM6fjWhkaL6cCMoNZH,
            "product_price":81,
            "product_description":"Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer quis lacus ex. Proin at feugiat turpis",
            "vel mattis diam. Vivamus consectetur eu felis in ultrices.",
            "product_name":"Chicken Burger"
         }
      ]
   },
   {
      "category_name":"Waffle",
      "category_id":VFjZZuWzgNWuCyx2MMl3,
      "category_products":[
         {
            "product_discount_price":48,
            "product_image":"http......"
            "product_id":LxgZgF0dugQzIGpXe8Md,
            "product_price":58,
            "product_description":"Waffle açıklmaso",
            "product_name":"Waffle"
         }
      ]
   }
]

Must use new value instead of old state

class MenuOptionsResult extends StateNotifier<List<dynamic>> {
  MenuOptionsResult() : super([]);

  void setOptions(options) {
    state = [...options];
  }

  void updateOption(getterIndex, index, value) {
    state[getterIndex]["product_options_content"][index]['isSelected'] = value;
    setOptions(state);
  }
}

Use OnDispose method in provider

final menuOptionsResultProvider =
    StateNotifierProvider<MenuOptionsResult, List<dynamic>>((ref) {
  ref.onDispose(() {/* dispose something here */});
  return MenuOptionsResult();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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