【问题标题】:How to save nested list with sqflite in flutter?如何在颤振中使用 sqflite 保存嵌套列表?
【发布时间】:2020-08-29 13:05:20
【问题描述】:

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

This Image shows you how I get data from APIs

我正在使用这个 sn-p 来保存带有 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 中使用SQflite databasesave dataget data。我如何做到这一点?

【问题讨论】:

    标签: database flutter dart sqflite


    【解决方案1】:

    这是一个老问题,希望您已经得到答案。然而,许多使用 sqflite 的颤振开发者在处理嵌套数组格式中提到的类型的数据时遇到了困难,例如

    ``` {
      "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, name, image1, image2, image3,...].

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

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

    ```
    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 中处理嵌套数组

    【讨论】:

      【解决方案2】:

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

      你需要用你想要的数据调用这个提供者的方法:

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

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

      DBProvider.createProductData(productData) //insert data
      

      获取数据

      DBProvider.getProductDataList() //get data 
      

      【讨论】:

      • 以上显示代码我用于列表项为[{id,name,},{id,name},{id, name},...],但我想将数据列表保存为[data:{id, name,image[image1, image2]},{id, name,image[image1, image2]},{id, name,image[image1, image2]},...]。那么,我该怎么做呢? @Anirudh Bagri
      • 您有什么理由要这样存储它吗?从数据库中检索数据后,您可以将列表放入另一个数据结构中。
      • 数据存储没有具体原因,但我从我的 WorkPlace 获取了这种格式的数据。这就是为什么我使用这种类型的数据。 @Anirudh Bagri。
      • 如果是这种情况,您可以将数组的每一项存储为 SQLite 中的一行。
      • 分享此类代码的任何参考链接,因为我是 Flutter 新手,因此请分享此参考链接。 @Anirush Bagri
      猜你喜欢
      • 1970-01-01
      • 2021-06-28
      • 2021-12-28
      • 2019-12-10
      • 2020-11-14
      • 2021-09-29
      • 2020-06-01
      • 2020-07-30
      • 1970-01-01
      相关资源
      最近更新 更多