what does type 'Future<dynamic>' is not a subtype of type 'Stream<dynamic>?' means?

454

Your displayPercentage function is marked as async which makes whatever the function returns wrapped into a Future automaticallu.

You are returning a Widget which makes the function's return type Future<Widget>. But since you have not mentioned it specifically while defining the function, dart is assuming it to Future<dynamic>.

Now, coming to your StreamBuilder, the parameter stream is supposed to be assigned a Stream. But you are assigning it your function which is actually a Future<dynamic>.

This is why it is giving the error saying that, it expects a Stream<dynamic> but you are giving it a Future<dynamic> and since Future is not a sub class that extends from Stream, the error says Future<dynamic> is not a subtype of type Stream<dynamic>.

To fix this, change your StreamBuilder into a FutureBuilder like this,

@override
Widget build(BuildContext context) {
  return Container(
    child: SafeArea(
      child: FutureBuilder(
        future: displayPercentage(),
        builder: (context, snapshot) {
          
          // since futures dont immediately give a value, if data is null the show loader
          if (snapshot.data == null) return CircularProgressIndicator();

          // Since data is not null, we can return Scaffold
          return Scaffold(
            appBar: AppBar(
              backgroundColor: Colors.lightGreen,
              title: Text('Student Welcome'),
              actions: <Widget>[
                TextButton.icon(
                    onPressed: () async {
                      // await _auth.signOut();
                      Navigator.of(context).pushNamed('/homepage');
                    },
                    icon: Icon(Icons.person),
                    label: Text('Logout'))
              ],
            ),
            // Since your Future holds the Center widget that you are sending, use it like this
            body: snapshot.data, 
          );
        },
      ),
    ),
  );
}
Share:
454
Learn
Author by

Learn

Updated on December 30, 2022

Comments

  • Learn
    Learn over 1 year

    Can someone please let me know where im doing wrong and what changes have to be done in the code in order to overcome this error of 'Future' is not a subtype of type 'Stream?'.Earlier the error was like Future' is not a subtype of type 'Widget' for which i wrapped the wwidget undet the StreamBuilder.Doing so resulted in this error.

    The below is the code which results in this error

    class _StudentDashboardState extends State<StudentDashboard> {
      userdetails userdetail;
      String res;
    
      final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
    
      final CollectionReference student_details =
          FirebaseFirestore.instance.collection('students');
      final CollectionReference tutor_details =
          FirebaseFirestore.instance.collection("tutors");
    
      String uid = FirebaseAuth.instance.currentUser.uid;
    
      @override
      void initState() {
        super.initState();
      }
    
      displayPercentage() async {
        var percentage = 0.0;
        var totalClassesTook;
        var totalClassesAttended;
        try {
          totalClassesTook = await tutor_details.doc(uid).get().then((doc) async {
            var val = await doc.data()['TotalClassesTook'];
            return val;
          });
    
          totalClassesTook = await totalClassesTook == null ? 0 : totalClassesTook;
    
          totalClassesAttended =
              await student_details.doc(uid).get().then((doc) async {
            var val = await doc.data()['TotalClassesAttended'];
            return val;
          });
          totalClassesAttended =
              await totalClassesAttended == null ? 0 : totalClassesAttended;
          percentage =
              await ((totalClassesAttended / totalClassesTook) * 100.0) / 100.0;
        } catch (e) {
          percentage = 0.0;
        }
        return Center(
          child: ListView(children: <Widget>[
            Padding(
              padding: EdgeInsets.symmetric(vertical: 150.0),
              child: new CircularPercentIndicator(
                radius: 120.0,
                lineWidth: 13.0,
                animation: true,
                percent: percentage,
                center: new Text(
                  "$percentage",
                  style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
                ),
                footer: Padding(
                  padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
                  child: new Text(
                    "Attendance Percentage",
                    style:
                        new TextStyle(fontWeight: FontWeight.bold, fontSize: 17.0),
                  ),
                ),
                circularStrokeCap: CircularStrokeCap.round,
                progressColor: Colors.purple,
              ),
            ),
          ]),
        );
      }
          @override
      Widget build(BuildContext context) {
         return Container(
          child: SafeArea(
            child: StreamBuilder(
                stream: displayPercentage(),
                builder: (context, snapshot) {
                  return Scaffold(
                    appBar: AppBar(
                      backgroundColor: Colors.lightGreen,
                      title: Text('Student Welcome'),
                      actions: <Widget>[
                        TextButton.icon(
                            onPressed: () async {
                              await _auth.signOut();
                              Navigator.of(context).pushNamed('/homepage');
                       
                        },
                        icon: Icon(Icons.person),
                        label: Text('Logout'))
                  ],
                ),
                body: 
                    displayPercentage(),
              );
            }),
      ),
    );
    

    }

  • Learn
    Learn almost 3 years
    great! That worked. But var val = await doc.data()['TotalClassesAttended']; in the displayPercentage() function changes dynamically , those realtime changes will reflect by using FutureBuilder? If not what is the alternative please let me know
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    In that case, you would still need to use StreamBuilder but you should get the snapshot instead of data. I suggest once you go thorugh the docs for getting realtime updates. If it is confusing tell me, Ill update the answer.
  • Learn
    Learn almost 3 years
    i have gone through the doc of StreamBuilder, but I'm a bit confused how can i use this in my case,in my code as im calling a displayPercentage() function. I'm unable to call the same function in "stream" of StreamBuilder.
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    Give me a few minutes, I will create a chat room and tell you there.
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
  • Learn
    Learn almost 3 years
    I must have atleast 20 reputation on Stack Overflow to be able to join chatroom?
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    I have upvoted your question, you must be more than 20 now
  • Learn
    Learn almost 3 years