假设一个列表被赋值给一个SQLite数据库的查询,如何保证这个列表不为空?扑

Assume a list is being assigned the query of a SQLite database, how to ensure that the list is not null? Flutter

我正在使用 sqflite 包制作一个带有 SQLite 数据库的 Flutter 应用程序。我有一个带有必要方法的数据库助手 class。在其中一个页面中,我想将数据显示为卡片列表。我还将图像存储到数据库中,因此在同一页面中我必须将图像转换回文件。在那个名为 DataPage 的页面的 class 中,我创建了一个名为 query 的方法,它调用数据库的查询方法并将该值分配给一个名为 listLokasi 的列表。我还制作了一个名为 convert 的方法,它调用 List.generate,其中一个参数是 listLokasi.length。同时,我将这 2 个方法放在 _DataPageState 的构造函数中,因为 DataPage 是一个有状态的小部件。问题是当我 运行 应用程序显示一个错误时显示 NoSuchMethodError,因为我试图在 null 上调用 length,这意味着 listLokasi 为 null。所以我将断言放在查询方法中,在查询方法之后的构造函数中,以及在转换方法中。结果是查询方法中的断言没有触发,而构造函数中的断言立即触发。我检查了我的数据库助手 class 并检查了我的代码,但我找不到我的代码中的缺陷。对此问题的任何帮助将不胜感激。我将在下面显示代码。

这是数据库助手 class。

class DatabaseHelper {
  static final _instance = DatabaseHelper._internal();

  DatabaseHelper._internal();

  factory DatabaseHelper() {
    return _instance;
  }

  Database db;

  Future initDatabase() async {
    var databasePath = await getDatabasesPath();
    var path = join(databasePath, 'table.db');
    db = await openDatabase(path, version: 1, onCreate: onCreate);
  }

  onCreate(Database db, int version) async {
    await db.execute('''
    CREATE TABLE lokasi 
    (id INTEGER PRIMARY KEY, 
    name TEXT, 
    description TEXT, 
    category TEXT, 
    latitude REAL, 
    longitude REAL, 
    image BLOB)
    ''');
  }

  Future<Lokasi> insert(Lokasi lokasi) async {
    await db.insert('lokasi', lokasi.toJson());
    return lokasi;
  }

  Future<List<Lokasi>> query() async {
    var list = await db.query('lokasi');
    return List.generate(list.length, (i) => Lokasi.fromJson(list[i]));
  }
}

这是数据页class。

class DataPage extends StatefulWidget {
  final savedUsername;
  const DataPage({this.savedUsername = 'User'});

  @override
  _DataPageState createState() => _DataPageState();
}

class _DataPageState extends State<DataPage> {
  DatabaseHelper db = DatabaseHelper();
  List<Lokasi> listLokasi;
  List<LokasiConvert> listLokasiConvert;

  _DataPageState() {
    query();
    assert(listLokasi != null);
    convert();
  }

  convert() {
    assert(listLokasi != null);
    listLokasiConvert = List.generate(
      listLokasi.length,
      (i) => LokasiConvert(
        name: listLokasi[i].name,
        description: listLokasi[i].category,
        category: listLokasi[i].category,
        latitude: listLokasi[i].latitude,
        longitude: listLokasi[i].longitude,
        image: File.fromRawPath(listLokasi[i].image),
      ),
    );
  }

  Future<List<Lokasi>> query() async {
    listLokasi = await db.query();
    assert(listLokasi != null);
    return listLokasi;
  }

  void sendUsername(BuildContext context) {
    String username = widget.savedUsername;
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => MainPage(username: username),
      ),
    );
  }

  void sendUsernameToChart(BuildContext context) {
    String chartUsername = widget.savedUsername;
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ChartPage(savedUsername: chartUsername),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text('Data'),
        actions: [
          RaisedButton(
            child: Text('Logout'),
            onPressed: () {
              Navigator.popUntil(context, ModalRoute.withName('/'));
            },
          ),
          RaisedButton(
            child: Text('Main'),
            onPressed: () {
              sendUsername(context);
            },
          ),
          RaisedButton(
            child: Text('Charts'),
            onPressed: () {
              sendUsernameToChart(context);
            },
          ),
        ],
      ),
      body: ListView.builder(
        itemBuilder: (context, i) {
          return Card(
              child: Row(
            children: [
              Image.file(
                listLokasiConvert[i].image,
                width: 100,
                height: 100,
              ),
              Column(
                children: [
                  Text(listLokasiConvert[i].name),
                  Text(listLokasiConvert[i].category),
                  Text(listLokasiConvert[i].description),
                  Text('Coordinates: ' +
                      listLokasiConvert[i].latitude.toString() +
                      ', ' +
                      listLokasiConvert[i].longitude.toString()),
                ],
              )
            ],
          ));
        },
        itemCount: listLokasiConvert.length,
      ),
    );
  }
}

再次感谢您的帮助。

也许你可以试试这个。希望对你有帮助。

db.query().then((value) {
  setState(() {
        listLokasi = value
  });
});

正如我在过程中发现的那样,解决方案实际上很简单。该列表是未来的,所以我应该使用未来的构建器,然后用未来的构建器包装列表视图构建器。让我展示一下我完成的那个特定页面的代码。

class DataPage extends StatefulWidget {
  final savedUsername;
  const DataPage({this.savedUsername = 'User'});

  @override
  _DataPageState createState() => _DataPageState();
}

class _DataPageState extends State<DataPage> {
  DatabaseHelper db = DatabaseHelper();
  List<Lokasi> listLokasi;

  delete(value) async {
    await db.delete(value);
  }

  Future<List<Lokasi>> query() async {
    listLokasi = await db.query();
    return listLokasi;
  }

  void sendUsername(BuildContext context) {
    String username = widget.savedUsername;
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => MainPage(username: username),
      ),
    );
  }

  void sendUsernameToChart(BuildContext context) {
    String chartUsername = widget.savedUsername;
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ChartPage(savedUsername: chartUsername),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text('Data'),
        actions: [
          RaisedButton(
            child: Text('Logout'),
            onPressed: () {
              Navigator.popUntil(context, ModalRoute.withName('/'));
            },
          ),
          RaisedButton(
            child: Text('Main'),
            onPressed: () {
              sendUsername(context);
            },
          ),
          RaisedButton(
            child: Text('Charts'),
            onPressed: () {
              sendUsernameToChart(context);
            },
          ),
        ],
      ),
      body: FutureBuilder(
        future: query(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemBuilder: (context, i) {
                return Card(
                  child: Row(
                    children: [
                      Column(
                        children: [
                          Text(snapshot.data[i].name),
                          Text(snapshot.data[i].category),
                          Text(snapshot.data[i].description),
                          Text('Coordinates: ' +
                              snapshot.data[i].latitude.toString() +
                              ', ' +
                              snapshot.data[i].longitude.toString()),
                        ],
                      ),
                      Container(
                        width: 100,
                        height: 100,
                        child: Image.memory(snapshot.data[i].image),
                      ),
                      Container(
                        width: 30,
                        height: 30,
                        child: IconButton(
                          onPressed: () {
                            db.delete(snapshot.data[i].name);
                            setState(() {});
                          },
                          icon: Icon(Icons.delete, size: 30),
                          iconSize: 30,
                        ),
                      )
                    ],
                  ),
                );
              },
              itemCount: snapshot.data.length,
            );
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}