1

I have exercises stored in my sqflite database as strings. I would like to retrieve the data and put it into a list or array called typeArray[]. I am trying to retrieve the data in a class that will use the list of exercises in functions to perform random workout generation. Therefore I need to retrieve the list before doing the calculations. The return values of these workout generator functions is then passed using MaterialPageRoute() to custom_workout_screen.dart where I use the return values of the functions to be displayed as strings to the screen.

I got it to work with predefined list ie where I had set the list = ['exerciseOne', 'exerciseTwo', 'etc']

How would I pull the data in a class that is not stateless or statefull? I am happy to do the work, but am confused in terms of the approach to the problem - any guidance appreciated!

Generates Custom Workout to be passed to the Custom Workout Screen: 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;
  }

DatabaseHelper: 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;
  }
}

Screen which uses output: 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);
              },
            ),
          ],
        ),
      ),
    );
  }
}

1 Answer 1

2

There are basically two approaches to your problem [as far as I know, probably more]. The first approach is by using Provider package. Below I will explain that approach in details:

First approach

Assuming that you already have your DatabaseHelper file you can define a class for your randomly picked workout [something like this, but not necessarily this way]. To simplify and focus on a concept I assume that Database has following fields: 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,
  });
}

Then you need to crate workout_provider.dart file to handle all provider related functions [adding, removing, fetching, but let use focus on fetching and setting]:

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

In your main.dart file you will need to wrap your MaterialApp widget with Provider widget of your choice (MultiProvider/Provider).

Finally in your file where you plan to populate the data you can use FutureBuilder to asynchronously fetch data from the database with future being Provider.of<TaskProvider>(context, listen: false).fetchAndSetWorkouts() and using Consumer's builder to retrieve the items getter from workout_provider.dart.

This is probably a lot to grasp, so I would recommend you visiting Provider package's documentation page as well as examples on GitHub, there are plenty of people who could explain better than me

Second approach

It is a simpler method, but is less flexible and efficient. You just asynchronously use DatabaseHelper directly where you need data as follows:

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;
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.