yazicifatihcan
yazicifatihcan

Reputation: 73

How to assign value to variable from future before screen built?

In my application user can have multiple home and multiple rooms for each home. On top of my application I have dropdown box which im trying to set default value to selectedHome by user. Below that dropdown box I am showing the rooms in the home selected by user. In firebase I have rooms collection under each home. I'm getting the selected home data from firebase too. Also to show the rooms in selected home i need to query by home name. I have two FutureBuilder as you can see code below. One of them to get the selectedHome data from firebase and other for the getting the rooms in that home from firebase. As I said before to get the rooms in selected home I need to query by name of the home so I have a parameter which is the value of dropdownbox. In my code the problem is getting the rooms part is working before I get the selectedHome data from firebase and assign it to dropdown value. In this case I'm getting "Null check operator used on a null value".

Basicly the question is how can i assign value from future to variable before screen gets build.

Here you can see the code for getting selected home data from firebase;

Future<String> selectedHome() async {
return await database.selectedHome();

}

Future<String> selectedHome() async {
DocumentSnapshot docS =
    await firestore.collection("users").doc(auth.currentUser()).get();
String selectedHome = (docS.data() as Map)["selectedHome"];
return selectedHome;

}

Here you can see the code for getting room data based on selectedHome from firebase;

Future<List<Map>> deviceAndRoomInfo() async {
    return database.numberOfRooms(_dropdownValue!);
  }

Future<List<Map>> numberOfRooms(String selectedHome) async {
    List<Map> prodsList = [];
    final snapshot = await firestore
        .collection("users")
        .doc(auth.currentUser())
        .collection("homes")
        .doc(selectedHome)
        .collection("rooms")
        .get();

    List listOfRooms = snapshot.docs;

    for (int a = 1; a <= listOfRooms.length; a++) {
      var productsInRoom = await firestore
          .collection("users")
          .doc(auth.currentUser())
          .collection("homes")
          .doc(selectedHome)
          .collection("rooms")
          .doc(listOfRooms[a - 1]["roomName"])
          .collection("products")
          .get();

      List prodList = productsInRoom.docs
          .map((e) => DeviceModel.fromMap(e.data()))
          .toList();

      Map qq = {
        "roomName": listOfRooms[a - 1]["roomName"],
        "deviceInfo": prodList
      };
      prodsList.add(qq);
    }
    return prodsList;
  }

Here you can see the code for screen contains 2 future builder that i told;

     import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:shelly_ess_production/constants.dart';
    import 'package:shelly_ess_production/helper_widgets/loading_widget.dart';
    import 'package:shelly_ess_production/screens/home_screen/components/circle_room_data.dart';
    import 'package:shelly_ess_production/screens/home_screen/components/device_in_room_card.dart';
    import 'package:shelly_ess_production/screens/home_screen/provider/home_screen_provider.dart';
    import 'package:shelly_ess_production/screens/models/device_model.dart';
    import 'package:shelly_ess_production/size_config.dart';

class Body extends StatefulWidget {
  const Body({Key? key}) : super(key: key);

  @override
  State<Body> createState() => _BodyState();
}

class _BodyState extends State<Body> {
 

  @override
  Widget build(BuildContext context) {
    var providerHelper =
        Provider.of<HomeScreenProvider>(context, listen: false);

    return SafeArea(
      child: Padding(
        padding:
            EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(0.07)),
        child: SingleChildScrollView(
            child: Column(
          children: [
            SizedBox(
              height: getProportionateScreenHeight(0.02),
            ),
            Consumer<HomeScreenProvider>(builder: (context, data, child) {
              return FutureBuilder<List<String>>(
                  future: data.getHomesAndSelected(),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      data.setDropDownValue = snapshot.data![0];
                      return DropdownButtonHideUnderline(
                        child: DropdownButton(
                          iconEnabledColor: kPrimaryColor,
                          iconDisabledColor: kPrimaryColor,
                          style: TextStyle(
                              color: kPrimaryColor,
                              fontSize: getProportionateScreenHeight(0.05)),
                          menuMaxHeight: getProportionateScreenHeight(0.4),
                          borderRadius: BorderRadius.circular(15),
                          key: UniqueKey(),
                          value: data.dropdownValue,
                          isExpanded: true,
                          icon: const Icon(Icons.arrow_downward),
                          onChanged: (String? newValue) async {
                            data.setDropDownValue = newValue;
                            await data.changeSelectedHome();
                          },
                          items: snapshot.data!
                              .map<DropdownMenuItem<String>>((String value) {
                            return DropdownMenuItem<String>(
                              alignment: Alignment.center,
                              value: value,
                              child: Text(value),
                            );
                          }).toList(),
                        ),
                      );
                    } else {
                      return Transform.scale(
                        scale: 0.5,
                        child: const Center(
                          child: CircularProgressIndicator(),
                        ),
                      );
                    }
                  });
            }),
            SizedBox(
              height: getProportionateScreenHeight(0.02),
            ),
            SizedBox(
              height: getProportionateScreenHeight(0.14),
              child: ListView.builder(
                  shrinkWrap: true,
                  scrollDirection: Axis.horizontal,
                  itemCount: 5,
                  itemBuilder: (context, index) {
                    return CircleRoomData(
                      title: "Oda Sayısı",
                      icon: Icons.meeting_room,
                      content: "8",
                    );
                  }),
            ),
            Consumer<HomeScreenProvider>(builder: (context, data, snapshot) {
              return FutureBuilder<List<Map>>(
                  future: data.deviceAndRoomInfo(data.dropdownValue!),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return ListView.builder(
                          physics: const NeverScrollableScrollPhysics(),
                          itemCount: snapshot.data!.length,
                          shrinkWrap: true,
                          itemBuilder: (context, index) {
                            return Column(
                              children: [
                                Divider(
                                  thickness:
                                      getProportionateScreenHeight(0.002),
                                ),
                                Text(
                                  snapshot.data![index]["roomName"],
                                  style: TextStyle(
                                      fontWeight: FontWeight.bold,
                                      color: kSecondaryColor,
                                      fontSize:
                                          getProportionateScreenHeight(0.03)),
                                ),
                                SizedBox(
                                  height: getProportionateScreenHeight(0.01),
                                ),
                                Text(
                                  "${(snapshot.data![index]["deviceInfo"] as List).length.toString()} Cihaz",
                                  style:
                                      const TextStyle(color: kSecondaryColor),
                                ),
                                SizedBox(
                                  height: getProportionateScreenHeight(0.02),
                                ),
                                GridView.builder(
                                    shrinkWrap: true,
                                    physics:
                                        const NeverScrollableScrollPhysics(),
                                    itemCount: (snapshot.data![index]
                                            ["deviceInfo"] as List)
                                        .length,
                                    gridDelegate:
                                        const SliverGridDelegateWithFixedCrossAxisCount(
                                      crossAxisCount: 3,
                                    ),
                                    itemBuilder: (context, indexx) {
                                      print(index);
                                      return DeviceInRoom(
                                        icon: Icons.light,
                                        productName: ((snapshot.data![index]
                                                    ["deviceInfo"]
                                                as List)[indexx] as DeviceModel)
                                            .deviceName,
                                      );
                                    })
                              ],
                            );
                          });
                    } else {
                      return const Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                  });
            }
            )
          ],
        )),
      ),
    );
  }
}

Upvotes: 0

Views: 314

Answers (1)

Tim
Tim

Reputation: 172

Am not certain where your error is coming from, but from what I see it maybe as a result of one of your functions returning null and a rendering of your content happens before the data is received.

You could try one of these:

You could declare the return type of your feature as being nullable for example you are expecting a value of type int:

Future<int?> xyz(){
  ......
  return .....;
}

Now because your return type is nullable you wont have an issues as long as the receiving variable is also nullable.

Alternatively:

Future<int?> xyz(){
  ......
  return ..... ?? 10 /*some default value*/;
}

because you know you result could be null you could also provide an optional default value incase your Future call returns a null value.

Upvotes: 1

Related Questions