skip to Main Content

I am working on an app which has the below dart files.

  1. Holderscreen.dart
  2. dashboard.dart
  3. Kitchen.dart
    I am passing the information from the holder page to the other pages like below

On the initialization of the app and calling the getUserDate returns userRes which is a type of future<map<string,dynamic> but after doing an update in Kitchen screen I recall the method in holder.dart file which refreshes/gets the userRes again but this time it is a type of _map<string,dynamic> because of which the kitchen screen shows the exception

Any idea what is going on. Based on suggestions I will share my code as asked, dont want to add a lot of code and cause confusion for the community

HolderClass

class HolderScreen extends StatefulWidget {
      
      
      @override
      _MyHolderPageState createState() => _MyHolderPageState();
    }
    
    class _MyHolderPageState extends State<HolderScreen> {
      PageController pageController = PageController();
      SideMenuController sideMenu = SideMenuController();
      Future<Map<String, dynamic>> tempUserRes = {} as Future<Map<String, dynamic>>;
      @override
      void initState() {
        sideMenu.addListener((index) {
          pageController.jumpToPage(index);
        });
        super.initState();
        tempUserRes = getUserData();
        print(tempUserRes.runtimeType);
        
      }
    
    Future<void> getUserDataForeignFunc() async {
          Future<Map<String, dynamic>> userRes;
          userRes = await getUserProfileData(widget.accessToken, widget.ivString, widget.profileType);
           print(tempUserRes.runtimeType);
        print(userRes.runtimeType);
          setState(() {
            tempUserRes = userRes;
          });
        print(tempUserRes.runtimeType);
        print(userRes.runtimeType);
        
        
      }
    Future<Map<String, dynamic>> getUserData() async {
        Future<Map<String, dynamic>> userRes;
        userRes = await getUserProfileData(widget.accessToken, widget.ivString, widget.profileType);
        print(tempUserRes.runtimeType);
        print(userRes.runtimeType);
        return userRes;
      }
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
            centerTitle: true,
          ),
          body: Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              SideMenu(
                controller: sideMenu,
                style: SideMenuStyle(
                  // showTooltip: false,
                  displayMode: SideMenuDisplayMode.auto,
                  showHamburger: true,
                  hoverColor: Colors.blue[100],
                  selectedHoverColor: Colors.blue[100],
                  selectedColor: Colors.lightBlue,
                  selectedTitleTextStyle: const TextStyle(color: Colors.white),
                  selectedIconColor: Colors.white,
                  // decoration: BoxDecoration(
                  //   borderRadius: BorderRadius.all(Radius.circular(10)),
                  // ),
                  // backgroundColor: Colors.grey[200]
                ),
                items: [
                  
                  SideMenuItem(
                    
                    title: 'Dashboard',
                    onTap: (index, _) {
                      sideMenu.changePage(index);
                    },
                    icon: const Icon(Icons.home),
                    badgeContent: const Text(
                      '3',
                      style: TextStyle(color: Colors.white),
                    ),
                    tooltipContent: "This is a tooltip for Dashboard item",
                  ),
                  SideMenuItem(
                    title: 'Kitchen',
                  
                    onTap: (index, _) {
                      sideMenu.changePage(index);
                    },
                    icon: const Icon(Icons.supervisor_account),
                  ),
                  SideMenuExpansionItem(
                    title: "Expansion Item",
                    icon: const Icon(Icons.kitchen),
                    children: [
                      SideMenuItem(
                        title: 'Expansion Item 1',
                        onTap: (index, _) {
                          sideMenu.changePage(index);
                        },
                        icon: const Icon(Icons.home),
                        badgeContent: const Text(
                          '3',
                          style: TextStyle(color: Colors.white),
                        ),
                        tooltipContent: "Expansion Item 1",
                      ),
                      SideMenuItem(
                        title: 'Expansion Item 2',
                        onTap: (index, _) {
                          sideMenu.changePage(index);
                        },
                        icon: const Icon(Icons.supervisor_account),
                      )
                    ],
                  ),
                  SideMenuItem(
                    title: 'Files',
                    onTap: (index, _) {
                      sideMenu.changePage(index);
                    },
                    icon: const Icon(Icons.file_copy_rounded),
                    trailing: Container(
                        decoration: const BoxDecoration(
                            color: Colors.amber,
                            borderRadius: BorderRadius.all(Radius.circular(6))),
                        child: Padding(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 6.0, vertical: 3),
                          child: Text(
                            'New',
                            style: TextStyle(fontSize: 11, color: Colors.grey[800]),
                          ),
                        )),
                  ),
                  SideMenuItem(
                    title: 'Download',
                    onTap: (index, _) {
                      sideMenu.changePage(index);
                    },
                    icon: const Icon(Icons.download),
                  ),
                  SideMenuItem(
                    builder: (context, displayMode) {
                      return const Divider(
                        endIndent: 8,
                        indent: 8,
                      );
                    },
                  ),
                  SideMenuItem(
                    title: 'Settings',
                    onTap: (index, _) {
                      sideMenu.changePage(index);
                    },
                    icon: const Icon(Icons.settings),
                  ),
                  // SideMenuItem(
                  //   onTap:(index, _){
                  //     sideMenu.changePage(index);
                  //   },
                  //   icon: const Icon(Icons.image_rounded),
                  // ),
                  // SideMenuItem(
                  //   title: 'Only Title',
                  //   onTap:(index, _){
                  //     sideMenu.changePage(index);
                  //   },
                  // ),
                  const SideMenuItem(
                    title: 'Exit',
                    icon: Icon(Icons.exit_to_app),
                  ),
                ],
              ),
              const VerticalDivider(width: 0,),
              Expanded(
                child: PageView(
                  controller: pageController,
                  children: [
                    //DashboardScreen(userRes: tempUserRes),
                    KitchenScreen(accessToken:widget.accessToken, userRes: tempUserRes, profileType: widget.profileType, ivString: widget.ivString, notifyParent: getUserDataForeignFunc),
                    Container(
                      color: Colors.white,
                      child: const Center(
                        child: Text(
                          'Expansion Item 1',
                          style: TextStyle(fontSize: 35),
                        ),
                      ),
                    ),
                    Container(
                      color: Colors.white,
                      child: const Center(
                        child: Text(
                          'Expansion Item 2',
                          style: TextStyle(fontSize: 35),
                        ),
                      ),
                    ),
                    Container(
                      color: Colors.white,
                      child: const Center(
                        child: Text(
                          'Files',
                          style: TextStyle(fontSize: 35),
                        ),
                      ),
                    ),
                    Container(
                      color: Colors.white,
                      child: const Center(
                        child: Text(
                          'Download',
                          style: TextStyle(fontSize: 35),
                        ),
                      ),
                    ),
    
                    // this is for SideMenuItem with builder (divider)
                    const SizedBox.shrink(),
    
                    Container(
                      color: Colors.white,
                      child: const Center(
                        child: Text(
                          'Settings',
                          style: TextStyle(fontSize: 35),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }

KitchenClass

class KitchenScreen extends StatefulWidget {
  final Future<Map<String, dynamic>> userRes;
  final String accessToken;
  final String profileType;
  final String ivString;
  final Function() notifyParent;
  const KitchenScreen({Key? key, required this.accessToken, required this.userRes, required this.profileType, required this.ivString, required this.notifyParent}) : super(key: key);
  @override
  State<KitchenScreen> createState() => _KitchenScreenState();
}

class _KitchenScreenState extends State<KitchenScreen> {
  bool showAddKitchenForm = false;
  @override
  void initState() {
    super.initState();
    showAddKitchenForm = false;
  }

  bool _showPassword = false;
  Future<void> showAddKitchenFormFunc() async {
    print("sadf");
    setState(() {
      showAddKitchenForm = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;
    return Scaffold(
        body: Center(
      child: FutureBuilder<Map<String, dynamic>>(
          future: widget.userRes,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Container(
                  height: size.height,
                  width: size.width,
                  color: Colors.blueGrey,
                  child: const Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              }
            }
            String firstName = snapshot.data != null ? snapshot.data!['firstName']: '';
            String lastName = snapshot.data != null ? snapshot.data!['lastName']: '';
            String email = snapshot.data != null ? snapshot.data!['email']: '';
            var userHasKitchen = false;
            if (snapshot.data != null && snapshot.data!['kitchen'] == null) {
              userHasKitchen = false;
            } else if (snapshot.data != null &&  snapshot.data!['kitchen'] != null &&
                snapshot.data!['kitchen'].length == 0) {
              userHasKitchen = false;
            } else if (snapshot.data != null &&  snapshot.data!['kitchen'] != null &&
                snapshot.data!['kitchen'].length > 0) {
              userHasKitchen = true;
            }
            if (!userHasKitchen && !showAddKitchenForm) {
              return GFButton(
                onPressed: () {
                  showAddKitchenFormFunc();
                },
                text: "Add Kitchen",
                size: GFSize.LARGE,
                fullWidthButton: true,
                icon: Icon(Icons.kitchen_outlined),
              );
            } else if (userHasKitchen && !showAddKitchenForm) {
              return Container(
                width: size.width,
                padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
                decoration: BoxDecoration(
                    color: const Color(0xFF48484A),
                    borderRadius: BorderRadius.circular(5)),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text('Last Name has kitchen:',
                        style: TextStyle(fontSize: 16, color: Colors.white38)),
                    const SizedBox(height: 7),
                    Text(lastName,
                        style:
                            const TextStyle(fontSize: 19, color: Colors.white)),
                  ],
                ),
              );
            } else if (showAddKitchenForm) {
              
              return KitchenFormPage(accessToken: widget.accessToken, profileType: widget.profileType, ivString: widget.ivString, notifyParent: widget.notifyParent);
            }
            return Container();
          }),
    ));
  }
}

KitchenForm.dart

class KitchenFormPage extends StatefulWidget {
  final String accessToken;
  final String profileType;
  final String ivString;
  final Function() notifyParent;
  const KitchenFormPage({Key? key, required this.accessToken, required this.profileType, required this.ivString, required this.notifyParent}) : super(key: key);

  @override
  _KitchenFormPageState createState() => _KitchenFormPageState();
}

class _KitchenFormPageState extends State<KitchenFormPage> {
  int currentStep = 0;
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  TextEditingController kitchenNameController = TextEditingController();
  TextEditingController kitchenDescriptionController = TextEditingController();
  TextEditingController kitchenAddress1Controller = TextEditingController();
  TextEditingController kitchenAddress2Controller = TextEditingController();
  TextEditingController kitchenCityController = TextEditingController();
  TextEditingController kitchenStateController = TextEditingController();
  TextEditingController kitchenZipCodeController = TextEditingController();

  Future<void> saveOrUpdateKitchenFunc() async {
    if (_formKey.currentState!.validate()) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: const Text('Processing Data'),
        backgroundColor: Colors.green.shade300,
      ));

      Map<String, dynamic> kitchenData = {
        'kitchenName': kitchenNameController.text,
        'kitchenDescription': kitchenDescriptionController.text,
        'kitchenAddress1': kitchenAddress1Controller.text,
        'kitchenAddress2': kitchenAddress2Controller.text,
        'kitchenCity': kitchenCityController.text,
        'kitchenState': kitchenStateController.text,
        'kitchenZipCode': kitchenZipCodeController.text,
        'action':'Save'

      };

      dynamic res = await saveOrUpdateKitchen(widget.accessToken, kitchenData, widget.profileType, widget.ivString);

      ScaffoldMessenger.of(context).hideCurrentSnackBar();

      if (res['ErrorCode'] == null) {
       widget.notifyParent();
      } else {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('Error: ${res['Message']}'),
          backgroundColor: Colors.red.shade300,
        ));
      }
    }
    
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Adding a Kitchen",
          ),
          centerTitle: true,
        ),
        body: Form(
            key: _formKey,
            child: Container(
                padding: const EdgeInsets.all(20),
                child: Stepper(
                  controlsBuilder: (BuildContext ctx, ControlsDetails dtl) {
                    return Row(
                      children: <Widget>[
                        GFButton(
                          onPressed: currentStep == 1?  saveOrUpdateKitchenFunc : dtl.onStepContinue,
                          shape: GFButtonShape.square,
                          child: Text(currentStep != 1 ? 'Continue' : 'Save'),
                        ),
                        Spacer(),
                        Visibility(
                            child: GFButton(
                              onPressed: dtl.onStepCancel,
                              shape: GFButtonShape.square,
                              child: Text(currentStep != 1 ? '' : 'Cancel'),
                            ),
                            visible: currentStep != 1 ? false : true),
                      ],
                    );
                  },
                  type: StepperType.vertical,
                  currentStep: currentStep,
                  onStepCancel: () => currentStep == 0
                      ? null
                      : setState(() {
                          currentStep -= 1;
                        }),
                  onStepContinue: () {
                    if (kitchenNameController.text.isEmpty &&
                        currentStep == 0) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content:
                            Text('Error: Kitchen Name is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else if (kitchenDescriptionController.text.isEmpty &&
                        currentStep == 0) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content: Text(
                            'Error: Kitchen Description is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else if (kitchenAddress1Controller.text.isEmpty &&
                        currentStep == 1) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content: Text(
                            'Error: Kitchen Address 1 is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else if (kitchenCityController.text.isEmpty &&
                        currentStep == 1) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content:
                            Text('Error: Kitchen City is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else if (kitchenStateController.text.isEmpty &&
                        currentStep == 1) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content:
                            Text('Error: Kitchen State is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else if (kitchenZipCodeController.text.isEmpty &&
                        currentStep == 1) {
                      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                        content: Text(
                            'Error: Kitchen Zip Code is a required field.'),
                        backgroundColor: Colors.red.shade300,
                      ));
                    } else {
                      bool isLastStep = (currentStep == getSteps().length - 1);
                      if (isLastStep) {
                      } else {
                        setState(() {
                          currentStep += 1;
                        });
                      }
                    }
                  },
                  onStepTapped: (step) => setState(() {
                    currentStep = step;
                  }),
                  steps: getSteps(),
                ))),
      ),
    );
  }

  List<Step> getSteps() {
    return <Step>[
      Step(
        state: currentStep > 0 ? StepState.complete : StepState.indexed,
        isActive: currentStep >= 0,
        title: const Text("Kitchen Info"),
        content: Column(
          children: [
            CustomInput(
              hint: "Kitchen Name",
              inputBorder: OutlineInputBorder(),
              controller: kitchenNameController,
              validatorValue: kitchenNameController.text,
               validationType: 'text',
            ),
            CustomInput(
              hint: "Kitchen Description",
              inputBorder: OutlineInputBorder(),
              controller: kitchenDescriptionController,
              validatorValue: kitchenDescriptionController.text,
               validationType: 'text',
            ),
          ],
        ),
      ),
      Step(
        state: currentStep > 1 ? StepState.complete : StepState.indexed,
        isActive: currentStep >= 1,
        title: const Text("Kitchen Address"),
        content: Column(
          children: [
            CustomInput(
              hint: "Address 1",
              controller: kitchenAddress1Controller,
              inputBorder: OutlineInputBorder(),
              validatorValue: kitchenAddress1Controller.text,
               validationType: 'text',
            ),
            CustomInput(
              hint: "Address 2",
              controller: kitchenAddress2Controller,
              inputBorder: OutlineInputBorder(),
              validatorValue: kitchenAddress2Controller.text,
               validationType: 'text',
            ),
            CustomInput(
              hint: "City",
              controller: kitchenCityController,
              inputBorder: OutlineInputBorder(),
              validatorValue: kitchenCityController.text,
              validationType: 'text',
            ),
            CustomInput(
              hint: "State",
              controller: kitchenStateController,
              inputBorder: OutlineInputBorder(),
              validatorValue: kitchenStateController.text,
               validationType: 'text',
            ),
            CustomInput(
              hint: "Postal Code",
              controller: kitchenZipCodeController,
              inputBorder: OutlineInputBorder(),
              validatorValue: kitchenZipCodeController.text,
               validationType: 'number',
            ),
          ],
        ),
      ),
    ];
  }
}

3

Answers


  1. Chosen as BEST ANSWER

    I was able to resolve it via the following changes

    Future<void> getUserDataForeignFunc() async {
        Map<String, dynamic> userRes;
        userRes = await getUserProfileData(
            widget.accessToken, widget.ivString, widget.profileType);
        setState(() {
          tempUserRes = Future.value(userRes);**--- added this to return as future map**
        });
      }
    
      Future<Map<String, dynamic>> getUserData() async {
        Future<Map<String, dynamic>> userRes;
        userRes = await getUserProfileData(
            widget.accessToken, widget.ivString, widget.profileType);
        return userRes;
      }
    

  2. You can clearly see that you are await a future result here:

    dynamic userRes;
    userRes = await getUserProfileData(widget.accessToken, widget.ivString, widget.profileType);
    

    then you are getting the result as dynamic userRes, it’s no longer a future but you return it as one.

    Login or Signup to reply.
  3. The one error I can spot is in the function getUserDataForeignFunc().

    Future<void> getUserDataForeignFunc() async {
      Future<Map<String, dynamic>> userRes;
      userRes = await getUserProfileData(
          widget.accessToken, widget.ivString, widget.profileType);
      setState(() {
        tempUserRes = userRes; // <--- userRes is of type Map<String, dynamic> !!!
      });
    }
    

    Since you await getUserProfileData() the type will be Map<String, dynamic>, the type of the completed future.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search