在 Flutter 中将带有图像的对象本地存储在磁盘上的最佳方法?

Best way to store objects with images locally on disk in Flutter?

我正在为一个人制作一本超级简单的食谱(就像字面上的食物)应用程序,所以我一直没有想过我 want/need 使用数据库或任何互联网连接。当用户创建菜谱时,菜谱对象包含一堆字符串和一张图片,像这样:

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


....
}


用户可能会创建大约 20 个食谱。不需要任何配置文件,因为我实际上只是在为一个人制作应用程序。食谱是唯一需要保留的应用程序数据。

到目前为止,我已尝试将每个食谱编码为 JSON,然后将其保存到 shared_preferences(请注意我为此目的尝试使用的 _imageBytes 字段)。但这不仅看起来是一种非常低效的做事方式,而且我什至无法让它发挥作用。获得这方面的信息似乎令人困惑:通常如何在不使用数据库的情况下将此类信息本地存储在 Flutter 应用程序中?或者数据库是解决问题的方法吗?

您需要路径提供程序包和 flutter 缓存管理器。

以下示例演示了如何使用缓存管理器存储网络图像。

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

要使用本地数据库在 Flutter 中高效地持久化数据,例如SQLite,方法是:

  1. 导入正确的依赖项:
import 'dart:async';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
  1. 打开数据库:
WidgetsFlutterBinding.ensureInitialized();
// Open the database and store the reference.
final Future<Database> database = openDatabase(
  join(await getDatabasesPath(), 'recipes_database.db'),
);
  1. 创建 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. 创建插入和检索条目的方法:
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
    );
  });
}

由于我们的 class、Recipe 包含文件,更具体地说是图像,我们可以将 Image 存储为 URL 并利用 Cache 检索它:

var image = await DefaultCacheManager().getSingleFile(recipe.picture);