流完成检索数据之前,列表视图引发错误 [英] List view throws an error before stream has finished retrieving data

查看:82
本文介绍了流完成检索数据之前,列表视图引发错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习Flutter,并遵循有关Provider软件包的在线教程,目前我正在使用StreamProvider.

我有一个连接到Firestore并返回集合中所有文档(报告")的服务,然后将这些文档映射到我的报表对象.

服务:

class FirestoreService {
Firestore _db = Firestore.instance;
var random = Random();

Stream<List<Report>> getReports() {
return _db.collection('reports')
      .orderBy('timeStamp', descending: true)
      .snapshots()
      .map((snapshot) => snapshot.documents
      .map((document) => Report.fromJson(document.data))
      .toList());
}

报告类别:

class Report {
final int temp;
final String wax;
final String line;
final String timeStamp;

Report({this.line,this.temp,this.timeStamp,this.wax});

Report.fromJson(Map<String, dynamic> parsedJson)
 : temp = parsedJson['temp'],
   wax = parsedJson['wax'],
   line = parsedJson['line'],
   timeStamp = parsedJson['timeStamp'];

}

main.dart内,我已使用MultiProvider并添加了StreamProvider.

main.dart:

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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {

final FirestoreService _db = FirestoreService();

return MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (BuildContext context) => SettingsProvider()),
    StreamProvider(create: (BuildContext context) => _db.getReports(),)
  ],
  child: MaterialApp(
    title: 'Wax App',
    theme: ThemeData(
        primarySwatch: Colors.deepPurple,
        accentColor: Colors.deepOrangeAccent),
    home: Home(),
  ),
 );
}}

现在是问题所在,在home.dart中,我检索报告数据并构建列表视图,但是在getReports方法完成之前调用了列表视图,并且在引用var reports <时偶尔会引发错误/p>

home.dart:

class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
var reports = Provider.of<List<Report>>(context);
FirestoreService _db = FirestoreService();

return Scaffold(
  appBar: AppBar(
    title: Text('Wax App'),
    centerTitle: true,
    actions: <Widget>[
      IconButton(
          icon: Icon(Icons.settings),
          onPressed: () {
            Navigator.of(context)
                .push(MaterialPageRoute(builder: (context) => Settings()));
          })
    ],
  ),
  body: ListView.builder(
      itemCount: reports.length,
      itemBuilder: (context, index) {
        Report report = reports[index];
        return ListTile(
            leading: Text(report.temp.toString()),
            title: Text(report.wax),
            subtitle: Text(report.line),
            trailing: Text(formatDate(DateTime.parse(report.timeStamp), [h, ':', mm, ' ', am])));
      }
      ) ,
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          _db.addReport();
        },
      ),
);
}}

例如,特别是在此行上引发了一个错误:

itemCount: reports.length

此时报告为null,所以我的问题是如何防止在getReports方法完成之前构建列表视图?处理此类任务的最佳方法是什么?

谢谢

解决方案

尝试一下:

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var reports = Provider.of<List<Report>>(context);
    FirestoreService _db = FirestoreService();

    return Scaffold(
      appBar: AppBar(
        title: Text('Wax App'),
        centerTitle: true,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.settings),
              onPressed: () {
                Navigator.of(context)
                    .push(MaterialPageRoute(builder: (context) => Settings()));
              })
        ],
      ),
      body: reports!=null ? (reports.length > 0 ? ListView.builder(
          itemCount: reports.length,
          itemBuilder: (context, index) {
            Report report = reports[index];
            return ListTile(
                leading: Text(report.temp.toString()),
                title: Text(report.wax),
                subtitle: Text(report.line),
                trailing: Text(formatDate(DateTime.parse(report.timeStamp), [h, ':', mm, ' ', am])));
          }
      ): Center(child: Text("We have received no data")))   : Center(child: Text("We are fetching data.Please wait...")),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          _db.addReport();
        },
      ),
    );
  }}

I've been learning Flutter and following an online tutorial regarding Provider package, at present I'm working with StreamProvider.

I have a service which connects to Firestore and returns all documents within a collection ('reports'), these documents are then mapped to my report object.

Service:

class FirestoreService {
Firestore _db = Firestore.instance;
var random = Random();

Stream<List<Report>> getReports() {
return _db.collection('reports')
      .orderBy('timeStamp', descending: true)
      .snapshots()
      .map((snapshot) => snapshot.documents
      .map((document) => Report.fromJson(document.data))
      .toList());
}

Report class:

class Report {
final int temp;
final String wax;
final String line;
final String timeStamp;

Report({this.line,this.temp,this.timeStamp,this.wax});

Report.fromJson(Map<String, dynamic> parsedJson)
 : temp = parsedJson['temp'],
   wax = parsedJson['wax'],
   line = parsedJson['line'],
   timeStamp = parsedJson['timeStamp'];

}

Within main.dart I have used MultiProvider and added my StreamProvider.

main.dart:

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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {

final FirestoreService _db = FirestoreService();

return MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (BuildContext context) => SettingsProvider()),
    StreamProvider(create: (BuildContext context) => _db.getReports(),)
  ],
  child: MaterialApp(
    title: 'Wax App',
    theme: ThemeData(
        primarySwatch: Colors.deepPurple,
        accentColor: Colors.deepOrangeAccent),
    home: Home(),
  ),
 );
}}

Now this is the issue, within home.dart I retrieve the report data and build a list view, however the list view is called before the getReports method has finished and occasionally throws an error when referencing the var reports

home.dart:

class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
var reports = Provider.of<List<Report>>(context);
FirestoreService _db = FirestoreService();

return Scaffold(
  appBar: AppBar(
    title: Text('Wax App'),
    centerTitle: true,
    actions: <Widget>[
      IconButton(
          icon: Icon(Icons.settings),
          onPressed: () {
            Navigator.of(context)
                .push(MaterialPageRoute(builder: (context) => Settings()));
          })
    ],
  ),
  body: ListView.builder(
      itemCount: reports.length,
      itemBuilder: (context, index) {
        Report report = reports[index];
        return ListTile(
            leading: Text(report.temp.toString()),
            title: Text(report.wax),
            subtitle: Text(report.line),
            trailing: Text(formatDate(DateTime.parse(report.timeStamp), [h, ':', mm, ' ', am])));
      }
      ) ,
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          _db.addReport();
        },
      ),
);
}}

For example one error in particular is thrown on this line:

itemCount: reports.length

reports being null at this point, so my question is how can I prevent the list view being built before the getReports methods has finished? what's the best way to handle such task?

Thanks

解决方案

Try this:

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var reports = Provider.of<List<Report>>(context);
    FirestoreService _db = FirestoreService();

    return Scaffold(
      appBar: AppBar(
        title: Text('Wax App'),
        centerTitle: true,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.settings),
              onPressed: () {
                Navigator.of(context)
                    .push(MaterialPageRoute(builder: (context) => Settings()));
              })
        ],
      ),
      body: reports!=null ? (reports.length > 0 ? ListView.builder(
          itemCount: reports.length,
          itemBuilder: (context, index) {
            Report report = reports[index];
            return ListTile(
                leading: Text(report.temp.toString()),
                title: Text(report.wax),
                subtitle: Text(report.line),
                trailing: Text(formatDate(DateTime.parse(report.timeStamp), [h, ':', mm, ' ', am])));
          }
      ): Center(child: Text("We have received no data")))   : Center(child: Text("We are fetching data.Please wait...")),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          _db.addReport();
        },
      ),
    );
  }}

这篇关于流完成检索数据之前,列表视图引发错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆