【问题标题】:How do I use an async method to build a List Object?如何使用异步方法构建列表对象?
【发布时间】:2018-07-19 14:17:07
【问题描述】:

我收到一条错误消息,指出方法 .length 正在调用空对象 _genreList。

我正在使用异步方法从本地资产 sqlite 数据库中获取数据,该数据库是流派列表。然后我使用 ListView.builder 在屏幕上显示该列表。这是获取数据的代码...

Future getGenreData() async {

    Directory documentsDirectory = await getApplicationDocumentsDirectory();

    String path = join(documentsDirectory.path, "asset_sample_sqlite.db");

    ByteData data = await rootBundle.load(join("assets", "sample_sqlite.db"));

    List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

    await new File(path).writeAsBytes(bytes);

    Database db = await openDatabase(path);

    _genreList = await db.rawQuery('SELECT genre_name[] FROM tbl_genres');

    print(_genreList);

    await db.close();
  }

如何在 build Widget 方法中使用此方法,以便在使用 ListView.builder 时可以访问 _genreList?像这样..

@override
  Widget build(BuildContext context) {

    return Scaffold(

      body: new ListView.builder(
          itemCount: _genreList.length, //need to access the genreList here
          itemBuilder: (BuildContext context, int index) {
            return new Card(
              child: new ListTile(
                title: new Text("${_genreList[index]}"),
                onTap: () {
                  Navigator.push(context,
                  MaterialPageRoute(
                    builder: (context) => BookPage(id: index),
                  ),
                  );
                }
              ),
            );
          }
      ),
    );
  }

这里的最终目标是显示一个流派列表(来自我的 sqlite 数据库中的 tbl_genres),它能够将数据传递到下一页以显示书籍列表(来自我的 sqlite 数据库中的 tbl_books)与该类型有关。

【问题讨论】:

    标签: sqlite asynchronous dart flutter


    【解决方案1】:

    异步编程的全部意义在于,当您在后台执行耗时的工作时,您的用户界面可以保持活跃。因此,您需要(并且希望)在应用程序加载时显示 CircularProgressIndicator 甚至空白页面(例如 Container)。

    至少有以下两种方法:

    1. 使小部件有状态并引入状态字段loading,当您的数据(在另一个字段中)准备好时,您将其初始化为true 并设置为false。您的代码如下所示:
    import 'package:flutter/material.dart';
    
    class GenresPage extends StatefulWidget {
      @override
      _GenresPageState createState() => _GenresPageState();
    }
    
    class _GenresPageState extends State<GenresPage> {
      bool loading;
      List<String> genreNames;
    
      @override
      void initState() {
        super.initState();
    
        loading = true;
        getGenreData();
      }
    
      Future getGenreData() async {
        final genreData = await actuallyGetThoseNames();
    
        setState(() {
          genreNames = genreData;
          loading = false;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: !loading ? new ListView.builder(
            itemCount: genreNames.length,
            itemBuilder: (context, index) {
              return new Card(
                child: new ListTile(
                  title: new Text("${genreNames[index]}"),
                ),
              );
            },
          ) : CircularProgressIndicator(), // or Container()
        );
      }
    }
    
    1. 使用FutureBuilder。因此,您需要重构您的getGenreData 方法以将列表作为Future&lt;List&lt;String&gt;&gt; 返回。

    【讨论】:

    • 非常感谢,帮了大忙。
    猜你喜欢
    • 2014-09-28
    • 2017-06-17
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2011-01-23
    相关资源
    最近更新 更多