Search code examples
flutterfirebasegoogle-cloud-firestore

How to convert future to Stream method for getting the realtime change data


I want to get the real-time change data when I update data. I have tried future method, but it only get one time.I want to convert future to stream method. I read the Firebase document, but I have no idea how to do it. Can someone help me?

fromsnapshot

factory Medicine.fromSnapshot(DocumentSnapshot<Map<String, dynamic>> document){
    final data = document.data()!;
    return Medicine(
        id:data["id"],
        medicineName: data["name"],
        medicineType: data["type"],
        dosage: data["dosage"],
        startTime: data["startTime"],
        notice: data["notice"],
        image: data["image"],
        uid: data["userId"],
        status: data["status"],
        date: data["date"],
        desc: data["desc"],
        notiId: data["notiID"]

    );
  }

Here is the future method

Future<List<Medicine>> getAllMedRecord(String id) async {
    final snapshot = await _db.collection("ShareDate").doc(id).collection(
        "medicineReminder").get();
    final medicineData = snapshot.docs.map((e) => Medicine.fromSnapshot(e))
        .toList();
    return medicineData;
  }

future builder code

FutureBuilder<List<Medicine>>(
          future: controller.getAllMedRecord(currentUser!),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              if (snapshot.hasData) {
                return ListView.separated(
                  scrollDirection: Axis.vertical,
                  shrinkWrap: true,
                  separatorBuilder: (_, __) => const SizedBox(
                    height: 25,
                  ),
                  itemCount: snapshot.data!.length,
                  itemBuilder: (_, index) => GestureDetector(
                    onTap: () {
                      Medicine medicine = snapshot.data![index];
                      Get.to(() => MedicineDetailScreen(
                            medicine: medicine,
                          ));
                    },
                    child: Container(
                      height: snapshot.data![index].status! == "Pending"? 300 : 230,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(16),
                        color: tPrimaryColor,
                      ),
                      child: specialBackground(
                        top1: -140,
                        top2: 20,
                        height: 80,
                        child: Container(
                          padding: EdgeInsets.all(15),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                "Medicine Reminder",
                                style: Theme.of(context)
                                    .textTheme
                                    .headlineLarge!
                                    .apply(color: tDarkModeColor),
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                              ),
                              Text(
                                "Start Time: ${snapshot.data![index].startTime!}",
                                style: Theme.of(context)
                                    .textTheme
                                    .headlineMedium!
                                    .apply(
                                  color: tDarkModeColor,
                                ),
                              ),
                              Divider(color: tDarkModeColor,),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.start,
                                children: [
                                  Image(
                                    image: NetworkImage(
                                        snapshot.data![index].image!),
                                    height: 90,
                                    width: 90,
                                  ),
                                  SizedBox(width: 30,),
                                  Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      Text(
                                        "Name: ${snapshot.data![index].medicineName!}",
                                        style: Theme.of(context)
                                            .textTheme
                                            .headlineMedium!
                                            .apply(color: tDarkModeColor),
                                        maxLines: 1,
                                        overflow: TextOverflow.ellipsis,
                                      ),
                                      Text(
                                        "Type: ${snapshot.data![index].medicineType!}",
                                        style: Theme.of(context)
                                            .textTheme
                                            .headlineMedium!
                                            .apply(
                                              color: tDarkModeColor,
                                            ),
                                        maxLines: 2,
                                        overflow: TextOverflow.ellipsis,
                                      ),
                                      Text(
                                          "Status: ${snapshot.data![index].status!}",
                                          style: Theme.of(context)
                                              .textTheme
                                              .headlineMedium!
                                              .apply(
                                                  color: snapshot.data![index].status! == "Took" ? Colors.green : snapshot.data![index].status! == "Pending"? Colors.grey : Colors.red )),
                                    ],
                                  ),
                                ],
                              ),
                              snapshot.data![index].status! == "Pending"?
                              Column(
                                children: [
                                  SizedBox(height: 20,),
                                  Row(
                                    children: [
                                      Expanded(
                                          child: ElevatedButton(
                                            style:
                                            ElevatedButton.styleFrom(backgroundColor: Colors.green),
                                            onPressed: () {
                                              controller.markStatusAsTook(snapshot.data![index].date!);
                                            },
                                            child: Text("Took".toUpperCase(),
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .headlineMedium!
                                                    .apply(color: tWhiteColor)),
                                          )),
                                      SizedBox(
                                        width: 20,
                                      ),
                                      Expanded(
                                          child: ElevatedButton(
                                            style:
                                            ElevatedButton.styleFrom(backgroundColor: Colors.red),
                                            onPressed: () {
                                              controller.markStatusAsForget(snapshot.data![index].date!);
                                            },
                                            child: Text("Forgot".toUpperCase(),
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .headlineMedium!
                                                    .apply(color: tWhiteColor)),
                                          ))
                                    ],
                                  ),
                                ],
                              )
                                  : Container()
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                );
              } else if (snapshot.hasError) {
                return Center(child: Text(snapshot.error.toString()));
              } else {
                return const Center(child: Text('Something went wrong'));
              }
            } else {
              return Center(child: CircularProgressIndicator());
            }
          },
        ),

Get the real-time change data when I update data


Solution

  • In order to get real-time data from Firebase you need to change Future with Stream because Future will only call once and once the result is retrieved the Future Completes its promise.

    You can use this code :

    Stream<List<Medicine>> getAllMedRecord(String id) {
      return _db.collection("ShareDate").doc(id).collection("medicineReminder")
        .snapshots()
        .map((snapshot) => snapshot.docs.map((e) => Medicine.fromSnapshot(e)).toList());
    }