提供程序重建了窗口小部件,但是直到“热重启”都没有显示

问题描述

我正在构建一个Flutter应用程序,我从将来获得了一些数据,并且还通过changenotifier获得了相同的数据。逻辑是,尽管某些对象没有数据,因为它在等待将来,然后显示一个旋转的圆圈。我已经在应用程序中完成了此操作,并且当对象尚未接收到数据时,我有一个名为Loading()的小部件。我遇到的问题是我得到了数据,但什么也没显示

Here is what it should display and after performing a hot restart is the result

数据正确显示,直到我对应用程序执行热刷新。用大写字母R代替小写字母r。区别在于它会启动应用程序并删除所有聚合数据。

发生这种情况时,似乎数据已填满对象,但我假设它变得不为空,这意味着[]为空但不为空,并且“过快地”显示数据,这反过来对该窗口小部件不显示任何内容,直到我重新启动“ r”,显示上面的屏幕截图。

Shows what is happening when a hot refresh is done "R"

这是有问题的代码

import 'package:disc_t/Screens/LoggedIn/Classes/classtile.dart';
import 'package:disc_t/Screens/LoggedIn/Classes/classpage.dart';
import 'package:disc_t/Screens/LoggedIn/Classes/classpageroute.dart';
import 'package:disc_t/Services/database.dart';
import 'package:disc_t/models/user.dart';
import 'package:disc_t/shared/loading.dart';
import 'package:Flutter/material.dart';
import 'package:morpheus/page_routes/morpheus_page_route.dart';
import 'package:provider/provider.dart';

class ClassList extends StatefulWidget {
  @override
  _ClassListState createState() => _ClassListState();
}

class _ClassListState extends State<ClassList> {
  @override
  void initState() {
    ClassDatanotifier classdatanotif =
        Provider.of<ClassDatanotifier>(context,listen: false);
    // final user = Provider.of<User>(context);
    // getTheClasses(classdatanotif);
    // List<ClassData> d = classes;
  }

  @override
  Widget build(BuildContext context) {
    ClassDatanotifier classdatanotif = Provider.of<ClassDatanotifier>(context);

    List<ClassData> cData = Provider.of<List<ClassData>>(context);



    bool rebd = false;

    Widget checker(bool r) {
      if (cData == null) {
        return Loading();
      } else {
        if (rebd == false) {
          setState(() {
            rebd = true;
          });

          rebd = true;

          return checker(rebd);

          // return Text("Still Loading");
        } else {
          return PageView.builder(
              scrollDirection: Axis.horizontal,itemCount: cData.length,// controller: PageController(viewportFraction: 0.8),itemBuilder: (context,index) {
                return Hero(
                  tag: cData[index],child: GestureDetector(
                    onTap: () {
                      // Navigator.of(context).push(ClasspageRoute(cData[index]));
                      Navigator.push(
                          context,MorpheusPageRoute(
                              builder: (context) =>
                                  Classpage(data: cData[index]),transitiontochild: true));
                    },child: Classtile(
                      classname: cData[index].classname,description: cData[index].classdescription,classcode: cData[index].documentID,),);
              });
        }
      }
    }

    
    return checker(rebd);
  }
}

这是提供者的实现方式

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  // final DatabaseService ds = DatabaseService();
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        StreamProvider<User>.value(
          value: AuthService().user,// child: MaterialApp(
          //   home: Wrapper(),// ),ChangeNotifierProvider<ClassDatanotifier>(
          create: (context) => ClassDatanotifier(),FutureProvider(
          create: (context) => DatabaseService().fetchClassdata,)
      ],child: MaterialApp(home: Wrapper()),);
  }
}

这是为获取数据而运行的功能

Future<List<ClassData>> get fetchClassdata async {
    QuerySnapshot snapshot = await classesCollection.getDocuments();

    List<ClassData> _classList = List<ClassData>();

    snapshot.documents.forEach((element) async {
      QuerySnapshot pre = await Firestore.instance
          .collection("Classes")
          .document(element.documentID)
          .collection("Pre")
          .getDocuments();

      List<Preq> _preList = List<Preq>();

      pre.documents.forEach((preClass) {
        Preq preqData = Preq.fromMap(preClass.data);

        if (preClass.data != null) {
          _preList.add(preqData);
        }
      });

      ClassData data =
          ClassData.fromMap(element.data,element.documentID,_preList);

      if (data != null) {
        _classList.add(data);
      }
    });

    return _classList;
  }

解决方法

我认为您的提供商的逻辑很好,问题出在那

snapshot.documents.forEach((element) async {
...
}

forEach不是Future(因为异步,它里面是因为Future,而方法本身不是),所以代码第一次运行,它到达forEach,后者对每个值执行自己的Future并传播到下一行代码,即返回值,但该列表为空,因为forEach尚未完成。

在这种情况下,有一个特殊的Future.forEach,因此您可以等待value方法之后再运行下一行

Future<List<ClassData>> get fetchClassdata async {
QuerySnapshot snapshot = await classesCollection.getDocuments();

List<ClassData> _classList = List<ClassData>();

await Future.forEach(snapshot.documents,(element) async {
  QuerySnapshot pre = await Firestore.instance
      .collection("Classes")
      .document(element.documentID)
      .collection("Pre")
      .getDocuments();

  List<Preq> _preList = List<Preq>();

  pre.documents.forEach((preClass) {
    Preq preqData = Preq.fromMap(preClass.data);

    if (preClass.data != null) {
      _preList.add(preqData);
    }
  });

  ClassData data =
      ClassData.fromMap(element.data,element.documentID,_preList);

  if (data != null) {
    _classList.add(data);
  }
});

return _classList;
}

这里是similar problem,提供者为forEach。也许可以帮助您更好地了解