【问题标题】:Flutter - sqflite: How to change the order (index) of the persisted data?Flutter - sqflite:如何更改持久化数据的顺序(索引)?
【发布时间】:2020-09-03 13:11:10
【问题描述】:

我到处搜索过这个问题。也许我没有使用正确的搜索词。如果已经被问到,我很抱歉。如果发现是重复的,我会迅速删除它。

我是一个相当缺乏经验的编码员,所以这段代码肯定不是最好看的。不过希望可以理解。

问题:

  • 我有一个自定义 ListTiles 列表,其数据通过 sqflite 包保存。
  • 你对它所做的一切(改变它的信息)已经被持久化了
  • 问题是,我已经实现了 reorderables 0.3.2 包,以便可以通过拖放重新排序列表
  • 如何使订单更改应用于数据库?如何更改数据库中条形图块的顺序?
  • 它现在的工作方式是添加一个条形图,然后它会进入数据库。这是永远不会改变的顺序。
  • 如何将索引更改从拖放条到不同位置/索引应用到我的 sqflite 数据库?

我将留下呈现列表的代码、fetchAndSetBars 方法以及用于创建和更新 DB 的 DB 方法。如果我遗漏了任何人可能需要的任何信息,请告诉我。我会尽快放在这里

Image of the list ordered by DB

Image of altered list order. If you restart app it goes back to image 1

这是问题列表的代码:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:budget_mentor/models/bar_tile_data.dart';
import 'package:reorderables/reorderables.dart';

class BarTilesList extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return FutureBuilder(
     future:
         Provider.of<BarTileData>(context, listen: false).fetchAndSetBars(),
     builder: (ctx, snapshot) => snapshot.connectionState ==
             ConnectionState.waiting
         ? Center(
             child: CircularProgressIndicator(),
           )
         : Consumer<BarTileData>(
             builder: (context, barTileData, child) {
               ScrollController _scrollController =
                   PrimaryScrollController.of(context) ?? ScrollController();

               void _onReorder(int oldIndex, int newIndex) {
                 Widget row = barTileData.barTiles.removeAt(oldIndex);
                 barTileData.barTiles.insert(newIndex, row);
               }

               return Column(
                 children: <Widget>[
                   Expanded(
                     child: CustomScrollView(
                       controller: _scrollController,
                       slivers: <Widget>[
                         ReorderableSliverList(
                           delegate: ReorderableSliverChildBuilderDelegate(
                               (BuildContext context, int index) =>
                                   barTileData.barTiles[index],
                               childCount: barTileData.barTiles.length),
                           onReorder: _onReorder,
                         )
                       ],
                     ),
                   ),
                   Text('Placeholder'),
                 ],
               );
             },
           ),
   );
 }
}

FetchAndSetBars 方法:

Future<void> fetchAndSetBars() async {
 final dataList = await DBHelper.getBarTileDBData('user_bars');
 barTiles = dataList.map((bar) {
   final int colorHex = int.tryParse(bar['barColor']);
   final String valueKey = bar['barKey'];
   return BarTile(
     barTitle: bar['barTitle'],
     barColor: Color(colorHex),
     barWidth: bar['barWidth'],
     id: bar['barID'],
     key: ValueKey(valueKey),
   );
 }).toList();

 notifyListeners();
}

数据库创建代码:

    static Future<Database> barTilesDatabase() async {
 final dbPath = await sql.getDatabasesPath();
 return sql.openDatabase(path.join(dbPath, 'bars_tile_list.db'),
     onCreate: (db, version) {
   return db.execute(
       'CREATE TABLE user_bars($barTitle TEXT PRIMARY KEY, $barColor TEXT, $barWidth REAL, $barID TEXT, $barKey TEXT)');
 }, version: 5);
}

(插入和删除代码是标准的) 我猜要添加的唯一其他相关 DB 代码将是我的 updateDB 方法:

static updateUserBarsDB(
   String barTitle,
   Color barColor,
   double barWidth,
   String barID,
   String barKey) async {

 Database db = await DBHelper.barTilesDatabase();
 final String colorValueAsString = barColor.value.toString();

 Map<String, dynamic> updatedBarTile = {
   DBHelper.barTitle: barTitle,
   DBHelper.barColor: colorValueAsString,
   DBHelper.barWidth: barWidth,
   DBHelper.barID: barID,
   DBHelper.barKey: barKey,
 };

 String id = barID;
 await db.update('user_bars', updatedBarTile,
     where: '${DBHelper.barID} = ?', whereArgs: [id]);
 print(await db.query('user_bars'));
}

【问题讨论】:

    标签: sql database sqlite flutter sqflite


    【解决方案1】:

    好的,我正在尝试在我的应用程序中构建相同的东西,这里有一个关于如何处理的建议。我不是数据库专家,所以不能说这在数据库操作方面是否具有成本效益或优化。

    假设您在列表[0, 1, 2, 3] 中有以下元素。我选择这些数字是为了说明它们的指数。

    现在考虑以下操作。

    1. 将第一个元素从开始位置移动到最后一个位置。执行此操作后,列表将变为this -> [1, 2, 3, 0]。由此,我们可以理解,当一个元素从一个较小的位置值移动到一个较大的位置值时(0 -> 4),那么我们在这两个位置之间的所有元素都需要在它们的位置值中得到一个-1。所以位置 1 变为 0,位置 2 变为 1,以此类推。

    2. 将最后一个元素从最后一个位置移动到开始位置。执行此操作后,列表将变为 this -> [3, 0, 1, 2]。由此可知,当一个元素从较大的位置值移动到较小的位置值(3 -> 0)时,我们需要执行上述操作的逆操作,我们将所有位置值加1。存在于两个指数之间。所以当第 4 个元素(3)变成第 1 个元素(0)时,所有第 4 个元素以上和第 1 个位置以下(包括第 1 个位置)的元素都需要将它们的位置加一。


    来到问题的 SQL 部分。您的表格中可以有一个indexlist_postion 列,它对应于元素的位置。当重新排序操作发生时,您可以使用index 列更新数据库中的元素。

    使用 order-by 操作从表中读取任务的 Stream,基于它们的索引值以升序排列。对此的示例查询将是

    SELECT * FROM tasks_table ORDER BY list_index ASC
    

    希望这会有所帮助,我不确定这种方法在大型列表中的性能,我目前正在寻找其他一些方法和算法来以更快的方式做到这一点。但就目前而言,它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 2016-12-05
      • 2021-05-10
      • 1970-01-01
      • 2022-10-13
      • 2013-04-17
      • 1970-01-01
      相关资源
      最近更新 更多