Flutter模型加载插件dartlcemodel的使用
Flutter 模型加载插件 dartlcemodel 的使用
简介
DartLceModel
是一个用于 Dart 平台的反应式数据加载库,旨在加载数据并报告操作状态(Loading
/Content
/Error
)。
特点
- 使用广泛的设计模式,包含
Loading
/Content
/Error
状态。 - 使用缓存作为“真理来源”,支持
CacheThenNetLceModel
。 - 检查数据的有效性(如是否最新)。
- 如果刷新失败,则回退到无效的缓存数据,允许离线应用使用。
- 支持数据的刷新或更新以实现重新加载或服务器数据更新操作。
- 缓存可以独立于加载进行失效处理,允许延迟数据更新和复杂数据关联。
- 可扩展的架构。
- 经过充分测试。
示例
该项目包含一个示例应用,该应用会:
- 加载 GitHub 用户的仓库列表,并缓存结果数据。
- 外部失效缓存,使活动监听器重新加载数据。
目录
- 设置依赖
- LceState
- LceModel
- CacheThenNetLceModel
- 获取和缓存数据
- 选择 EntityValidator
- 显示无效数据和缓存回退
- 缓存失效和数据更新
- 按需缓存重新获取
- 缓存服务实现
- 在小部件中设置模型的完整示例
- 获取仅数据流和流变换
- 状态变换
设置依赖
$ dart pub add dartlcemodel
LceState
LceState
是一种现代的应用架构方法,建议将应用程序的组合状态打包到一个不可变的状态对象流中。每个对象应包含处理、转换和显示所需的所有数据集。除了数据本身之外,最常用的信息是数据加载管道的状态。
/// Loading 类型
enum LoadingType {
/// 正在加载。可能是初始加载操作
loading,
/// 加载更多项目以供分页视图使用
loadingMore,
/// 刷新内容
refreshing,
/// 更新服务器上的数据
updating
}
LceModel
LceState
在这个库中由简单的用例接口生成。
/// 基础 LCE 用例,具有 [state] 和 [refresh] 属性
/// [DATA] 被加载的数据类型
abstract class LceUseCase<DATA extends Object> {
/// 模型状态。订阅开始数据加载。当最后一个订阅者取消时,模型取消内部组件的数据更新
Stream<LceState<DATA>> get state;
/// 请求刷新数据。数据将在异步中更新
Future<void> refresh();
}
CacheThenNetLceModel
这种类型的模型首先尝试从缓存中获取数据,如果未找到或缓存数据已过期,则从网络加载数据。以下是使用此类型模型进行数据加载的序列图。
final useCase = LceModel.cacheThenNet(
'params', // 参数标识要加载的数据
serviceSet, // 一组缓存+网络服务
startWith: const LceState.loading(null, false), // 可选初始状态,在订阅时发出
logger: logger // 可选日志记录器以了解用例内部情况
);
获取和缓存数据
缓存模型使用两个服务从网络获取数据并在本地存储它。
- NetService - 从网络加载数据。
- CacheService - 将数据保存在本地。
选择 EntityValidator
以下是一些可用的验证器:
- Simple - 一个初始化为有效状态的简单数据类。
- Never - 从未有效的。
- Always - 始终有效的。
- Lifespan - 一个初始化为时间有效期值的验证器,到期后变为无效。
显示无效数据和缓存回退
当网络连接不可用时,你可以回退到缓存数据。如果没有可用的缓存数据,你只会得到 null
作为 data
属性的值。
缓存失效和数据更新
当某些事情发生在另一个部分时,复杂的应用程序可能需要刷新部分应用程序中的某些数据。例如,当收到推送通知时,刷新聊天应用的消息列表。使用反应式缓存服务,这种失效可以通过简单而干净的方式完成。
/// 全局可用的服务集
late ServiceSet<List<Repository>, String> serviceSet;
void main() {
// 创建一组服务
// - 数据的内存缓存
// - 从服务器获取数据的服务。`isolated()` 在 [Isolate] 中运行网络请求和解析
serviceSet = ServiceSet(
CacheService<List<Repository>, String>.withSyncDelegate(MemoryCacheDelegate.map()),
RepositoryNetService().isolated()
);
runApp(const MyApp());
}
// 后续在小部件中
final refresh = GestureDetector(
onTap: () async {
await serviceSet.cache.invalidateAll();
},
child: const Icon(
Icons.refresh,
size: 26.0,
)
);
按需缓存重新获取
考虑一个具有复杂内部结构的缓存服务,该服务通过某种内部逻辑进行更新。例如,数据库保存实体并直接更新记录。在这种情况下,你需要某种方式来通知数据更改的订阅者。
/// 缓存服务有两个方法可以调用,使其重新获取数据并更新其活动客户端
class CacheService {
Future<void> refetch(P params); // 完成
Future<void> refetchAll(); // 完成
}
缓存服务实现
虽然你可以实现任何缓存服务,但库附带了一个简单的 AsyncDelegateCacheService
和 SyncDelegateCacheService
,它们使用以下异步/同步委托进行数据 I/O。
final cache = CacheService<SomeData, String>.withSyncDelegate(MemoryCacheDelegate.map());
在小部件中设置模型的完整示例
class LceWidget<D extends Object> extends StatefulWidget {
final String params;
const LceWidget({Key? key, required this.params}) : super(key: key);
[@override](/user/override)
State<LceWidget<D>> createState() => _LceWidgetState();
}
class _LceWidgetState<D extends Object> extends State<LceWidget<D>> {
LceUseCase<D>? _useCase;
StreamSubscription<LceState<D>>? _subscription;
late LceState<D> _lceState;
[@override](/user/override)
void initState() {
super.initState();
_subscribe();
}
[@override](/user/override)
void didUpdateWidget(LceWidget<D> oldWidget) {
super.didUpdateWidget(oldWidget);
// 检查是否需要加载另一组数据
if (widget.params != oldWidget.params) {
_unsubscribe();
_subscribe();
}
}
[@override](/user/override)
void dispose() {
super.dispose();
_unsubscribe();
}
_subscribe() {
// 初始状态以显示
_lceState = const LceState.loading(null, false);
_useCase = LceModel.cacheThenNet(
widget.params, // 参数标识要加载的数据
serviceSet // 一组缓存+网络服务 - 全局定义或通过 DI 提供
);
_subscription = _useCase!.state.listen((newLceState) {
setState(() { _lceState = newLceState; });
});
}
_unsubscribe() {
_subscription?.cancel();
_subscription = null;
_useCase = null;
}
Future<void> _refresh() async {
return _useCase?.refresh() ?? Future.value();
}
[@override](/user/override)
Widget build(BuildContext context) => lceState.when(
loading: (_) => const LoadingState(), // 加载小部件
content: (state) => ContentState(repositories: state.data), // 内容小部件
error: (state) => ErrorState(error: state.error, onRetry: () async { await _refresh(); }) // 错误小部件
);
}
更多关于Flutter模型加载插件dartlcemodel的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter模型加载插件dartlcemodel的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
dartlcemodel
是一个用于在 Flutter 应用中加载和管理机器学习模型的插件。它支持从本地或远程加载模型,并提供了一种简单的方式来使用这些模型进行推理。以下是如何使用 dartlcemodel
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 dartlcemodel
插件的依赖。
dependencies:
flutter:
sdk: flutter
dartlcemodel: ^0.1.0 # 请使用最新的版本号
然后运行 flutter pub get
来安装依赖。
2. 加载模型
dartlcemodel
支持从本地文件或远程 URL 加载模型。以下是两种加载方式的示例:
从本地文件加载模型
import 'package:dartlcemodel/dartlcemodel.dart';
Future<void> loadModelFromFile() async {
String modelPath = 'assets/model.tflite';
Model model = await Model.fromFile(modelPath);
print('Model loaded from file');
}
从远程 URL 加载模型
import 'package:dartlcemodel/dartlcemodel.dart';
Future<void> loadModelFromUrl() async {
String modelUrl = 'https://example.com/path/to/model.tflite';
Model model = await Model.fromUrl(modelUrl);
print('Model loaded from URL');
}
3. 使用模型进行推理
加载模型后,你可以使用它来进行推理。以下是一个简单的示例:
import 'package:dartlcemodel/dartlcemodel.dart';
Future<void> runInference() async {
String modelPath = 'assets/model.tflite';
Model model = await Model.fromFile(modelPath);
// 假设输入是一个包含 224x224 图像的 Float32List
List<double> input = List.filled(224 * 224 * 3, 0.0);
// 进行推理
List<double> output = await model.run(input);
print('Inference result: $output');
}
4. 处理输出
推理的结果通常是一个 List<double>
,你可以根据具体的模型和应用场景来处理这些输出。
5. 清理资源
在使用完模型后,确保释放资源以避免内存泄漏。
void disposeModel(Model model) {
model.dispose();
}
6. 错误处理
在使用 dartlcemodel
时,可能会遇到各种错误,例如模型加载失败或推理错误。确保在代码中适当地处理这些错误。
try {
Model model = await Model.fromFile('assets/model.tflite');
} catch (e) {
print('Failed to load model: $e');
}