在 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
,方法是:
- 导入正确的依赖项:
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
- 打开数据库:
WidgetsFlutterBinding.ensureInitialized();
// Open the database and store the reference.
final Future<Database> database = openDatabase(
join(await getDatabasesPath(), 'recipes_database.db'),
);
- 创建 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,
);
- 创建插入和检索条目的方法:
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);
我正在为一个人制作一本超级简单的食谱(就像字面上的食物)应用程序,所以我一直没有想过我 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
,方法是:
- 导入正确的依赖项:
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
- 打开数据库:
WidgetsFlutterBinding.ensureInitialized();
// Open the database and store the reference.
final Future<Database> database = openDatabase(
join(await getDatabasesPath(), 'recipes_database.db'),
);
- 创建 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,
);
- 创建插入和检索条目的方法:
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);