【问题标题】:what does type 'Future<dynamic>' is not a subtype of type 'Stream<dynamic>?' means?什么是“Future<dynamic>”类型不是“Stream<dynamic>”类型的子类型?方法?
【发布时间】:2021-08-12 04:16:00
【问题描述】:

谁能告诉我我哪里做错了,为了克服 'Future' is not a subtype of type 'Stream?' 的错误,必须在代码中进行哪些更改? 。之前的错误就像 Future' 不是“Widget”类型的子类型

以下是导致此错误的代码

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(),
          );
        }),
  ),
);

}

【问题讨论】:

    标签: android firebase flutter dart google-cloud-firestore


    【解决方案1】:

    您的displayPercentage 函数被标记为async,这使得函数返回的wrapped 变为Future 自动allu。

    您正在返回一个Widget,它使函数的返回类型为Future&lt;Widget&gt;。但是由于您在定义函数时没有具体提及它,所以dart 假设它为Future&lt;dynamic&gt;

    现在,来到您的StreamBuilder,参数stream 应该被分配一个Stream。但是你给它分配了你的函数,它实际上是一个Future&lt;dynamic&gt;

    这就是为什么它给出错误说,它需要一个Stream&lt;dynamic&gt;,但你给它一个Future&lt;dynamic&gt;,因为Future不是从Stream扩展的sub class,错误说Future&lt;dynamic&gt; is not a subtype of type Stream&lt;dynamic&gt;.

    要解决此问题,请将您的 StreamBuilder 更改为 FutureBuilder,如下所示,

    @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, 
              );
            },
          ),
        ),
      );
    }
    

    【讨论】:

    • 太棒了!那行得通。但是 displayPercentage() 函数中的var val = await doc.data()['TotalClassesAttended']; 是动态变化的,这些实时变化会通过使用 FutureBuilder 反映出来吗?如果不是什么替代方案,请告诉我
    • 在这种情况下,您仍然需要使用StreamBuilder,但您应该使用snapshot 而不是data。我建议您通读文档以获取实时更新。如果让我感到困惑,请告诉我,我会更新答案。
    • 我已经浏览了 StreamBuilder 的文档,但我有点困惑如何在我的情况下使用它,在我的代码中调用 displayPercentage() 函数。我无法在 StreamBuilder 的“流”中调用相同的函数。
    • 给我几分钟,我会创建一个聊天室并在那里告诉你。
    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2021-08-13
    • 2020-09-24
    • 2020-09-11
    • 2020-10-13
    • 2019-12-31
    相关资源
    最近更新 更多