Sohanuzzaman Soad
Sohanuzzaman Soad

Reputation: 29

Flutter : Why This Method Not Works?

In QuerySnapshot It Has "Day1" and "Day2" Boths are Day of Week Like "Saturday". If "Day1" or "Day2" is Today I need to Return "true". But This method always returns false. I need to know why the If condition (In Loop) is not working and How can I Solve this?

bool class_count(Stream<QuerySnapshot> stream) {
  bool class_ = false;
  String dateFormat = DateFormat('EEEE').format(DateTime.now());
  //This Line Return Day Like "Saturday"
  stream.forEach((element) {
    if (element != null) {
      for (int count = 0; count < element.documents.length; count++) {
        if (element.documents[count].data['Day1'].toString() == dateFormat)
          class_ = true;
        if (element.documents[count].data['Day2'].toString() ==
            dateFormat) if (element.documents[count].data['Day2']
                .toString() ==
            dateFormat) class_ = true;
      }
    }
  });
  print(class_);
  return class_;
}


Upvotes: 0

Views: 265

Answers (2)

dilshan
dilshan

Reputation: 2522

stream.forEach() method returns a Future type value. So you have to call this method inside a another Asynchronous function and also it needs to be await until that future completes.

Solution:-

  • Convert your class_count() synchronous method to a Asynchronous method by,

    1. Adding async keyword to method header.
    2. Change your return type into a Future<bool>.
  • Add await keyword before stream.forEach() method call (Asynchronous operation).

Code:-

[Read comments carefully to understand the program flow correctly]

//1- Return type should be a Future type => Future<bool>.
//2- Add async keyword before method body => async.
Future<bool> class_count(Stream<QuerySnapshot> stream) async{
  bool class_ = false;
  String dateFormat = DateFormat('EEEE').format(DateTime.now());

  //3 - Adding await keyword before asynchronous operation => await.
  //
  await stream.forEach((element) {
    if (element != null) {
      for (int count = 0; count < element.documents.length; count++) {
        if (element.documents[count].data['Day1'].toString() == dateFormat)
          class_ = true;
        if (element.documents[count].data['Day2'].toString() ==
            dateFormat) if (element.documents[count].data['Day2']
                .toString() ==
            dateFormat) class_ = true;
      }
    }
  });
  //After stream.forEach() method completes its loop these below statements will execute.
  //Every statements inside the function body will only execute one after another.
  //so below statements are only executes after the above operation completes.
  print(class_);
  return class_;
}

One extra tip :- By using StreamSubcription you can get streams of data, instead of future.

Upvotes: 0

BambinoUA
BambinoUA

Reputation: 7100

Bacause stream's forEach is asynchronous. So this loop will not wait while it completes. In your code you set class_ to false, then create a future which will be executed in future, and return classs_ at once. So it still equal to false.

Try to add async suffix to method and await before stream.forEach. And then your method must return Future<bool> and been called as

final class = await class_count(someStream);

I think the best way to handle stream events is add listener for stream and process data in it.

stream.listener((event) {
  // here must be your code which will be executed each time stream will get event
});

Upvotes: 3

Related Questions