繁体   English   中英

如何在 flutter 中使用 sqflite 保存嵌套列表?

[英]How to save nested list with sqflite in flutter?

在这里,我想在我的flutter新闻应用程序中添加bookmark功能。 我从APIs get数据。 我在下面显示该数据。

此图片向您展示了我如何从 API 获取数据

我正在使用这个片段来保存下面显示的SQflite数据。 我用名称bookmark_db_provider.dart保存这个文件。

import 'dart:io';

import 'home_screen_data.dart';
import 'package:path/path.dart';

import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

class DBProvider {
  static Database _database;
  static final DBProvider db = DBProvider._();

  DBProvider._();

  Future<Database> get database async {
    if (_database != null) _database = await initDB();

    return _database;
  }

  initDB() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    final path = join(documentsDirectory.path, 'ProductData.db');

    return await openDatabase(path, version: 1, onOpen: (db) {},
        onCreate: (Database db, int version) async {
      await db.execute('CREATE TABLE ProductData('
          'id INTEGER PRIMARY KEY,' //id
          'categoryName Text,' //headline
          'publisherName Text,'  //description
          'isAvailable Text,'      //content
          'categoryImgUrl Text'  //image
          ')');
    });
  }

  createProductData(ProductData productData) async {
    await deleteAllProductData();
    final db = await database;
    final res = await db.insert('ProductData', productData.toJson());

    return res;
  }

  Future<int> deleteAllProductData() async {
    final db = await database;
    final res = await db.delete('DELETE FROM ProductData');

    return res;
  }

  Future<List<ProductData>> getProductDataList() async {
    final db = await database;
    final res = await db.rawQuery("SELECT * FROM ProductData");

    List<ProductData> list = res.isNotEmpty ? res.map((x) => ProductData.fromJson(x)).toList() : [];

    return list;
  }
}

所以,我想了解如何使用 flutter 中的flutter SQflite database save dataget data 我如何做到这一点?

你的问题我可能不清楚,但根据我的理解,

您需要使用所需的数据调用此提供程序的方法:

DBProvider.init() // Use this only one which when the application is instaled

之后,您可以从任何地方调用这些方法来放置和获取数据

DBProvider.createProductData(productData) //insert data

获取数据

DBProvider.getProductDataList() //get data 

这是一个老问题,希望你已经得到了答案。 但是,许多使用 sqflite 的 flutter 开发人员在处理上述类型的嵌套数组格式的数据时遇到了困难,例如

``` {
  "id": 1,
  "name": "xyz",
  "images": [
    {
      "imageId": 1,
      "image": "image1"
    },
    {
      "imageId": 2,
      "image": "image2"
    }
  ]
} 
```

由于 json 处理目前不是 sqflite 的一部分,因此建议这样做; a.,将内部数组保存为表“数据”的“图像”列中的字符串/文本字段,如**

"[{"imageId": 1, "image": 'image1'}, {"imageId": 2, "image": 'image2'},}"

**,无担保。

或者,b.,将内部数组展平,以便只有 **

数据[id,名称,image1,image2,image3,...]。

** 这种方法可能在给定的简单数组中但在复杂系统中是可能的。 变平可能真的很麻烦。

我的建议是,创建两个表,一个用于数据,另一个用于图像。 让图像表的每一行都与对应的数据表行有引用或关系。 您的数据 class 和图像 class 将类似于,

```
class Data {
    int dataId;
    String name;
    List<Image> images;
    data({this.id, this.images, this.name});
    ...
``` 

``` 
class Image {    
    int imageId;
    int dataId;
    String image;
    Image({this.imageId, this.dataId, this.image});
    ...
    } 
```

您的 sqflite 表数据将只有两个字段“dataId”和“name”,并且图像表必须包含“dataId”作为两个表之间的关系。

要保存数据,您可以使用交易,例如

```
void saveData(Data data, Map<String, Object> map) async {
    await db.execute(""" INSERT INTO "data" (name) values (?) """, [data.name]);

// retrieve dataId of the new row inserted. last_inserted_rowid can also be used if the database does not contain several tables that may have been updated or saved before completing the transaction.
 
 int dataId;
    List<Map> x = await db.query('data', columns: ['dataId'], where: 'name = ?', whereArgs: [data.name]);
    dataId = x[x.length - 1]['dataId'];
   

    db.transaction((txn) async {
      var batch = txn.batch();
      data.images
          .map((e) => {
                batch.rawInsert(
                    """ INSERT INTO "images" (dataId,image,) values (?,?,?,? ) """, [dataId, e.image])
              }).toList();
    });
  }
 ```

要检索数据和图像,您可以尝试类似

 ```
 Data _data = new Data();
 
 Future<void> fetchData() async {
    if (db != null) {
      // do not execute if db is not instantiate
      //retrieve all data from data table and store in instantiated, also instantiate images array as empty list
      final dataList = await db.query(data);
      _data = (dataList as List)
          .map(
            (data) => Data(
              dataId: data['dataId'],
              name: data['name'],
             images: data['images'] != null ? data['images'] : []
            )) .toList();
    
      _data.forEach((data)  async {if (data.images != null) {
        List<Image> _images = [];
        var imageResults = await db.query(images,where: 'dataId =?', whereArgs: [data.dataId]);
      
        _images = (imageResults as List).map((e) => Image(
          imageId: e['imageId'],
          dataId: e['dataId'],
          image: e['image']
        )).toList();
        _data.images.addAll(_images);       
      }  });

    }
  }
  ```
 

使用这种方法,您应该能够处理 flutter 和 sqflite 中的嵌套数组

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM