0

I'm making a super simple cookbook (like literally, for food) app for one single person, so I haven't been thinking that I want/need to use a database or any internet connectivity. When the user creates a recipe, the recipe object contains a bunch of strings and an image, like this:

class Recipe {
 String _title;
  Image _picture;
  Uint8List _imageBytes;
  int _prepTime;
  int _cookTime;
  int _totalTime;
  String _description;
  List<String> _ingredientList;
  List<String> _directionsList;


....
}


The user will probably create around 20 recipes. There need not be any profiles, since I'm literally just making the app for one person. The recipes are the only app data that need to persist.

So far, I have tried to encode each recipe as a JSON and then save it to shared_preferences (note the _imageBytes field that I tried to use for this purpose). But not only does this seem like a really inefficient way to do things, I haven't even been able to get it to work. It seems confusingly difficult to get information on this: how would one normally store such information locally in a Flutter app, without using a database? Or is a database the way to go here?

Jackson
  • 31
  • 5

2 Answers2

1

To persist data efficiently in Flutter using a local database, such as SQLite, is the way to go:

  1. Import the right dependecies:
import 'dart:async';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
  1. Open the DB:
WidgetsFlutterBinding.ensureInitialized();
// Open the database and store the reference.
final Future<Database> database = openDatabase(
  join(await getDatabasesPath(), 'recipes_database.db'),
);
  1. Create the table:
final Future<Database> database = openDatabase(
  join(await getDatabasesPath(), 'doggie_database.db'),
  onCreate: (db, version) {
    return db.execute(
      "CREATE TABLE dogs(id INTEGER PRIMARY KEY, name TITLE)", // all the properties here
    );
  },
  version: 1,
);
  1. Create methods to insert and retrieve entries:
Future<void> inserRecipe(Recipe recipe) async {
  final Database db = await database;
  await db.insert(
    'recipe',
    recipe.toMap(),
    conflictAlgorithm: ConflictAlgorithm.replace,
  );
}
Future<List<Recipe>> recipes() async {
  final Database db = await database;

  final List<Map<String, dynamic>> maps = await db.query('recipes');

  return List.generate(maps.length, (i) {
    return Recipe(
      title: maps[i]['title'],
      // ... all the properties here
    );
  });
}

Since our class, Recipe, contains files, and more specifically images, we could store the Image as an URL and take advantage of the Cache to retrieve it:

var image = await DefaultCacheManager().getSingleFile(recipe.picture);
Stefano Amorelli
  • 4,553
  • 3
  • 14
  • 30
0

You need path provider package and flutter cache manager.

Following is an example that demonstrates how a network image can be stored with cache manager.

import 'dart:async';
import 'dart:io' as Io;
import 'package:image/image.dart';

import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:path_provider/path_provider.dart';
class SaveFile {

  Future<String> get _localPath async {
    final directory = await getApplicationDocumentsDirectory();

    return directory.path;
  }
  Future<Io.File> getImageFromNetwork(String url) async {

    var cacheManager = await CacheManager.getInstance();
    Io.File file = await cacheManager.getFile(url);
    return file;
  }

  Future<Io.File> saveImage(String url) async {

    final file = await getImageFromNetwork(url);
    //retrieve local path for device
    var path = await _localPath;
    Image image = decodeImage(file.readAsBytesSync());

    Image thumbnail = copyResize(image, 120);

    // Save the thumbnail as a PNG.
    return new Io.File('$path/${DateTime.now().toUtc().toIso8601String()}.png')
      ..writeAsBytesSync(encodePng(thumbnail));
  }
}