Flutter/Dart:检索 sqflite 数据并放入 array/list

Flutter/Dart: Retrieve sqflite data and put into an array/list

我将练习作为字符串存储在我的 sqflite 数据库中。我想检索数据并将其放入名为 typeArray[] 的列表或数组中。我正在尝试检索 class 中的数据,该数据将使用函数中的练习列表来执行随机锻炼生成。因此我需要在进行计算之前检索列表。然后使用 MaterialPageRoute() 将这些锻炼生成器函数的 return 值传递给 custom_workout_screen.dart,我在其中使用函数的 return 值在屏幕上显示为字符串。

我让它与预定义列表一起工作,即我设置列表的地方 = ['exerciseOne'、'exerciseTwo'、'etc']

我如何将数据拉入非无状态或有状态的 class 中?我很乐意做这项工作,但对解决问题的方法感到困惑 - 感谢任何指导!

生成要传递到自定义锻炼屏幕的自定义锻炼:generate_custom.dart

class GenerateCustom {
  int rnd;
  // NEED TO SET typeArray to values from SQFLITE DB ?
  List typeArray = [];

  GenerateCustom({this.difficulty});
  final int difficulty;
  String workout;
  String ex1;
  String ex2;
  String ex3;
  String ex4;
  String ex5;
  
  String getStrengthType() {
    var random = Random();
    var i = random.nextInt(14);
    print(typeArray[i]);
    return typeArray[i];
  }
  
  String cuExerciseOne() {
    if (difficulty == 1) {
      workout = ('1: ' +
          getStrengthType() +
          ' ' +
          getRepsEasy() +
          'x' +
          getSetsEasy());
    } else if (difficulty == 2) {
      workout = ('1: ' +
          getStrengthType() +
          ' ' +
          getRepsMedium() +
          'x' +
          getSetsMedium());
    } else {
      workout = ('1: ' +
          getStrengthType() +
          ' ' +
          getRepsHard() +
          'x' +
          getSetsHard());
    }
    return workout;
  }

数据库助手: database_helper.dart

class DatabaseHelper {
  static DatabaseHelper _databaseHelper;
  static Database _database;
  String exerciseTable = 'exercise_table';
  String colId = 'id';
  String title = 'title';

  DatabaseHelper._createInstance();
  factory DatabaseHelper() {
    if (_databaseHelper == null) {
      _databaseHelper = DatabaseHelper._createInstance();
    }
    return _databaseHelper;
  }

  Future<Database> get database async {
    if (_database == null) {
      _database = await initializeDatabase();
    }
    return _database;
  }

  Future<Database> initializeDatabase() async {
    //get ios + android dir path
    Directory directory = await getApplicationDocumentsDirectory();
    String path = directory.path + 'exercise.db';

    //Open or create db at path
    var exerciseDatabase =
        await openDatabase(path, version: 1, onCreate: _createDb);
    return exerciseDatabase;
  }

  void _createDb(Database db, int newVersion) async {
    await db.execute(
        'CREATE TABLE $exerciseTable ($colId INTEGER PRIMARY KEY, $title TEXT)');
  }

  Future<List<Map<String, dynamic>>> getExerciseMapList() async {
    Database db = await this.database;
    var result = await db.rawQuery('SELECT * FROM $exerciseTable');
    return result;
  }

  //Insert
  Future<int> insertExercise(Exercise exercise) async {
    Database db = await this.database;
    var result = await db.insert(exerciseTable, exercise.toMap());
    return result;
  }

  //Update
  Future<int> updateExercise(Exercise exercise) async {
    var db = await this.database;
    var result = await db.update(exerciseTable, exercise.toMap(),
        where: '$colId = ?', whereArgs: [exercise.id]);
    debugPrint('update called');
    return result;
  }

  //Delete
  Future<int> deleteExercise(int id) async {
    var db = await this.database;
    int result =
        await db.rawDelete('DELETE FROM $exerciseTable WHERE $colId = $id');
    return result;
  }

  //get no of objects in db
  Future<int> getCount() async {
    Database db = await this.database;
    List<Map<String, dynamic>> x =
        await db.rawQuery('SELECT COUNT (*) from $exerciseTable');
    int result = Sqflite.firstIntValue(x);
    return result;
  }

  //get Map list from db, convert to Exercise List object
  Future<List<Exercise>> getExerciseList() async {
    //get map list and # of entries in db
    var exerciseMapList = await getExerciseMapList();
    int count = exerciseMapList.length;

    List<Exercise> exerciseList = List<Exercise>();
    //Loop to create exercise list from a map list
    for (int i = 0; i < count; i++) {
      exerciseList.add(Exercise.fromMapObject(exerciseMapList[i]));
    }
    return exerciseList;
  }
}

使用输出的屏幕: custom_workout_screen.dart

class CustomWorkoutScreen extends StatelessWidget {
  CustomWorkoutScreen(
      this.customDifficulty,
      this.customWorkout1,
      this.customWorkout2,
      this.customWorkout3,
      this.customWorkout4,
      this.customWorkout5);
  final String customDifficulty;
  final String customWorkout1;
  final String customWorkout2;
  final String customWorkout3;
  final String customWorkout4;
  final String customWorkout5;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kBackgroundColour,
      appBar: AppBar(
        backgroundColor: kButtonAndBarColour,
        title: Text('CUSTOM', style: kTitleStyle),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            SizedBox(height: 15.0),
            Expanded(
              child: Text(
                'WORKOUT',
                style: kTitleStyleDark,
              ),
            ),
            Container(
              child: Text(
                'DIFFICULTY: ' + customDifficulty,
                style: kTitleStyleDark,
              ),
            ),
            SizedBox(
              height: 25.0,
            ),
            Container(
              margin: EdgeInsets.only(bottom: 10.0),
              child: Column(
                children: <Widget>[
                  Text('READY...GO!', style: kCommentTextStyle),
                  Text(
                    customWorkout1,
                    style: kMainTextStyledDark,
                  ),
                  Text('REST 30s!', style: kCommentTextStyle),
                  Text(
                    customWorkout2,
                    style: kMainTextStyledDark,
                  ),
                  Text('REST 30s!', style: kCommentTextStyle),
                  Text(
                    customWorkout3,
                    style: kMainTextStyledDark,
                  ),
                  Text('REST 30s!', style: kCommentTextStyle),
                  Text(
                    customWorkout4,
                    style: kMainTextStyledDark,
                  ),
                  Text('REST 30s!', style: kCommentTextStyle),
                  Text(
                    customWorkout5,
                    style: kMainTextStyledDark,
                  ),
                  Text('GOOD JOB, REST!', style: kCommentTextStyle),
                  Text('OR GO AGAIN?', style: kCommentTextStyle),
                ],
              ),
            ),
            SizedBox(
              height: 50.0,
            ),
            BottomButton(
              buttonTitle: 'NEW WORKOUT',
              onTap: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

基本上有两种方法可以解决您的问题[据我所知,可能更多]。第一种方法是使用 Provider package。下面我将详细解释该方法:

第一种方法

假设您已经有了 DatabaseHelper 文件,您可以为随机选择的锻炼定义 class [类似这样,但不一定是这样]。为了简化和关注一个概念,我假设数据库具有以下字段:difficulty TEXT PRIMARY KEY, workout1 TEXT, workout2 TEXT, workout3 TEXT, workout4 TEXT, workout5 TEXT

import 'package:flutter/foundation.dart';

class RandomWorkout {
  final String difficulty;
  final String workout1;
  final String workout2;
  final String workout3;
  final String workout4;
  final String workout5;

  RandomWorkout({
    @required this.difficulty,
    @required this.workout1,
    @required this.workout2,
    @required this.workout3,
    @required this.workout4,
    @required this.workout5,
  });
}

然后您需要创建 workout_provider.dart 文件来处理所有提供程序相关的功能 [添加、删除、获取,但让我们专注于获取和设置]:

class WorkoutProvider with ChangeNotifier {
  List<RandomWorkout> _workouts = [];

  List<Task> get items {
    return [..._tasks];
  }

  Future<void> fetchAndSetWorkouts() async {
    final dataList =
        await DBHelper.getExerciseMapList();

    _workouts = dataList
        .map(
          (item) => RandomWorkout(
            difficulty: item['difficulty'],
            workout1: item['workout1'],
            workout2: item['workout2'],
            workout3: item['workout3'],
            workout4: item['workout4'],
            workout5: item['workout5'],
          ),
        )
        .toList();

    notifyListeners();
  }
}

在您的 main.dart 文件中,您需要使用您选择的 Provider 小部件 (MultiProvider/Provider) 包装您的 MaterialApp 小部件。

最后,在您计划填充数据的文件中,您可以使用 FutureBuilder 从数据库中异步获取数据,未来为 Provider.of<TaskProvider>(context, listen: false).fetchAndSetWorkouts() 并使用 Consumer 的构建器来从 workout_provider.dart.

检索项目 getter

这可能有很多需要掌握的地方,所以我建议您访问 Provider 包的文档页面以及 GitHub 上的示例,有很多人比我解释得更好

第二种方法

这是一种更简单的方法,但灵活性和效率较低。您只需在需要数据的地方直接异步使用 DatabaseHelper 如下:

Future<List<RandomWorkout>> fetchAndSetWorkouts() async {
    final dataList =
        await DBHelper.getExerciseMapList();

    workouts = dataList
        .map(
          (item) => RandomWorkout(
            difficulty: item['difficulty'],
            workout1: item['workout1'],
            workout2: item['workout2'],
            workout3: item['workout3'],
            workout4: item['workout4'],
            workout5: item['workout5'],
          ),
        )
        .toList();

     return workouts;
  }