简体   繁体   English

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

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

Here I want to add bookmark functionality in my flutter news application.在这里,我想在我的flutter新闻应用程序中添加bookmark功能。 I get data from APIs .我从APIs get数据。 I display that data below.我在下面显示该数据。

This Image shows you how I get data from APIs此图片向您展示了我如何从 API 获取数据

I am using this snippet for saving data with SQflite which I display below.我正在使用这个片段来保存下面显示的SQflite数据。 I save this file with name bookmark_db_provider.dart .我用名称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;
  }
}

So, I want to how to save data and get data this with SQflite database in flutter .所以,我想了解如何使用 flutter 中的flutter SQflite database save dataget data How I accomplish this?我如何做到这一点?

I might be unclear with your question, but according to what I understood,你的问题我可能不清楚,但根据我的理解,

You need to call the method of this provider with data that you want:您需要使用所需的数据调用此提供程序的方法:

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

After that, you can call these methods from anywhere to put and get data之后,您可以从任何地方调用这些方法来放置和获取数据

DBProvider.createProductData(productData) //insert data

Get data获取数据

DBProvider.getProductDataList() //get data 

This is an old question and hopes you have gotten an answer to it.这是一个老问题,希望你已经得到了答案。 However, a lot of flutter dev using sqflite struggles with handling data in a nested array format of the type mentioned eg但是,许多使用 sqflite 的 flutter 开发人员在处理上述类型的嵌套数组格式的数据时遇到了困难,例如

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

Since json handling is not part of sqflite at the moment, it is suggested to either;由于 json 处理目前不是 sqflite 的一部分,因此建议这样做; a., save inner array as a string/text field in the 'image' column of table 'data' like ** a.,将内部数组保存为表“数据”的“图像”列中的字符串/文本字段,如**

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

**, no guaranty. **,无担保。

or, b., flatten out the inner array so as to have only **或者,b.,将内部数组展平,以便只有 **

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

** this approach may be possible in a simple array as given but in a complex system. ** 这种方法可能在给定的简单数组中但在复杂系统中是可能的。 flattening out may be really cumbersome.变平可能真的很麻烦。

my suggestion, create two tables, one for data, and another for images.我的建议是,创建两个表,一个用于数据,另一个用于图像。 let each row of images table have reference or relationship with corresponding data table row.让图像表的每一行都与对应的数据表行有引用或关系。 Your data class and images class will be something like,您的数据 class 和图像 class 将类似于,

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

and

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

Your sqflite table data will have only two fields 'dataId' and 'name' and the image table must include 'dataId' as the relationship between the two tables.您的 sqflite 表数据将只有两个字段“dataId”和“name”,并且图像表必须包含“dataId”作为两个表之间的关系。

to save data, you can use transactions like要保存数据,您可以使用交易,例如

```
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();
    });
  }
 ```

to retrieve data and images, you can try something like要检索数据和图像,您可以尝试类似

 ```
 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);       
      }  });

    }
  }
  ```
 

with that approach, you should be able to handle nested array in flutter and sqflite使用这种方法,您应该能够处理 flutter 和 sqflite 中的嵌套数组

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

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