提供商重建小部件,但直到 "Hot restart" 才显示任何内容
Provider rebuilds the widget, but nothing shows up until a "Hot restart"
我正在构建一个 flutter 应用程序,我从未来获得了一些数据,我也通过 changenotifier 获得了相同的数据。好吧,逻辑是,虽然某些对象没有数据,因为它等待未来,然后显示一个旋转的圆圈。我已经在应用程序中完成了此操作,并且当对象未接收到数据时,我有一个名为 Loading() 的小部件。 运行 我遇到的问题是我获取了数据,但它没有显示任何内容。
数据显示正确,直到我执行应用程序的热刷新。大写字母 R 而不是小写字母 r。不同之处在于它会启动应用程序并删除所有聚合数据。
当发生这种情况时,数据似乎填满了对象,但我假设它变得不为空,意思是 [] 为空但不为空,并且显示数据“太快”,这反过来又不显示任何内容小部件,直到我重新启动“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(它里面是一个未来,因为异步,但方法本身不是)所以代码第一次运行,它到达 forEach,它对每个值都有自己的未来并传播到下一行代码,return,但是列表是空的,因为 forEach 还没有完成。
对于这种情况有一个特殊的 Future.forEach,因此您可以在 运行 下一行
之前等待值方法
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;
}
这是一个 提供程序和 forEach。也许它可以帮助你更好地理解
我正在构建一个 flutter 应用程序,我从未来获得了一些数据,我也通过 changenotifier 获得了相同的数据。好吧,逻辑是,虽然某些对象没有数据,因为它等待未来,然后显示一个旋转的圆圈。我已经在应用程序中完成了此操作,并且当对象未接收到数据时,我有一个名为 Loading() 的小部件。 运行 我遇到的问题是我获取了数据,但它没有显示任何内容。
数据显示正确,直到我执行应用程序的热刷新。大写字母 R 而不是小写字母 r。不同之处在于它会启动应用程序并删除所有聚合数据。
当发生这种情况时,数据似乎填满了对象,但我假设它变得不为空,意思是 [] 为空但不为空,并且显示数据“太快”,这反过来又不显示任何内容小部件,直到我重新启动“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(它里面是一个未来,因为异步,但方法本身不是)所以代码第一次运行,它到达 forEach,它对每个值都有自己的未来并传播到下一行代码,return,但是列表是空的,因为 forEach 还没有完成。
对于这种情况有一个特殊的 Future.forEach,因此您可以在 运行 下一行
之前等待值方法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;
}
这是一个