Flutter依赖注入与状态管理插件riverpod_repo的使用
Flutter依赖注入与状态管理插件riverpod_repo的使用
概述
riverpod_repo
是一个用于生成基于仓库模式(Repository Pattern)的 Riverpod Providers 的代码生成器。仓库模式将数据访问和存储逻辑与应用程序的其他部分分离,提供了一致的数据访问接口。
使用步骤
1. 创建抽象类(仓库接口)
首先定义一个抽象类作为仓库接口:
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_repo/annotations.dart';
part 'data_repo.g.dart';
part 'data_repo.repo.dart';
@riverpodRepo
abstract class RepoData {
Future<List<String>> getBooks({String search = '', String categoryId = ''});
Future<List<int>> getTopGenres();
Future<List<bool>> getTopBooksByGenre(String genreId, {String search = ''});
Future<List<String>> getCategories({String search = ''});
}
2. 添加 @riverpodRepo
注解
在你的仓库接口类上添加 @riverpodRepo
注解。
3. 添加 part
指令
为 .g.dart
和 .repo.dart
文件添加 part
指令:
part 'data_repo.g.dart';
part 'data_repo.repo.dart';
4. 在 pubspec.yaml
中添加 riverpod_generator
确保在 pubspec.yaml
中添加 riverpod_generator
依赖:
dependencies:
riverpod: any
riverpod_annotation: any
dev_dependencies:
build_runner: any
riverpod_generator: any
5. 创建 Provider 来访问仓库实现
创建一个 Provider 来访问仓库的实现:
@Riverpod(keepAlive: true)
RepoData repoData(RepoDataRef ref) => RepoDataImpl();
6. 运行构建器
运行以下命令生成代码:
flutter pub run build_runner build --delete-conflicting-outputs
这将生成如下内容:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'data_repo.dart';
@riverpod
Future<List<String>> repoDataGetBooks(RepoDataGetBooksRef ref,
{String search = '', String categoryId = ''}) {
return ref.watch(repoDataProvider).getBooks(
search: search,
categoryId: categoryId,
);
}
@riverpod
Future<List<int>> repoDataGetTopGenres(
RepoDataGetTopGenresRef ref,
) {
return ref.watch(repoDataProvider).getTopGenres();
}
@riverpod
Future<List<bool>> repoDataGetTopBooksByGenre(
RepoDataGetTopBooksByGenreRef ref, String genreId,
{String search = ''}) {
return ref.watch(repoDataProvider).getTopBooksByGenre(
genreId,
search: search,
);
}
@riverpod
Future<List<String>> repoDataGetCategories(RepoDataGetCategoriesRef ref,
{String search = ''}) {
return ref.watch(repoDataProvider).getCategories(
search: search,
);
}
7. 使用生成的 Provider
你可以在应用中的任何地方使用这些生成的 Provider:
ref.watch(repoDataGetCategoriesProvider).when(
loading: () => const CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
data: (categories) {
return Text(categories.toString());
},
);
示例 Demo
完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_repo/annotations.dart';
part 'example.g.dart';
part 'example.repo.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final categoriesAsyncValue = ref.watch(repoDataGetCategoriesProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod Repo Example'),
),
body: Center(
child: categoriesAsyncValue.when(
loading: () => const CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
data: (categories) {
return ListView.builder(
itemCount: categories.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(categories[index]),
);
},
);
},
),
),
);
}
}
@Riverpod(keepAlive: true)
RepoData repoData(RepoDataRef ref) => RepoDataImpl();
@riverpodRepo
abstract class RepoData {
Future<List<String>> getBooks({String search = '', String categoryId = ''});
Future<List<int>> getTopGenres();
Future<List<bool>> getTopBooksByGenre(String genreId, {String search = ''});
Future<List<String>> getCategories({String search = ''});
}
class RepoDataImpl implements RepoData {
@override
Future<List<String>> getBooks({String search = '', String categoryId = ''}) async {
// Mock implementation
await Future.delayed(const Duration(seconds: 1));
return ['Book1', 'Book2'];
}
@override
Future<List<int>> getTopGenres() async {
// Mock implementation
await Future.delayed(const Duration(seconds: 1));
return [1, 2, 3];
}
@override
Future<List<bool>> getTopBooksByGenre(String genreId, {String search = ''}) async {
// Mock implementation
await Future.delayed(const Duration(seconds: 1));
return [true, false];
}
@override
Future<List<String>> getCategories({String search = ''}) async {
// Mock implementation
await Future.delayed(const Duration(seconds: 1));
return ['Category1', 'Category2'];
}
}
注意事项
- 提供者名称前缀:生成的 Provider 名称会以前缀的形式包含仓库类名。
- 仓库类名和为其创建的 Provider 名称应相同。
许可证
该软件遵循 MIT 许可证。
支持
如有问题,请联系 dilan@dilan.me 获取支持和示例应用。
更多关于Flutter依赖注入与状态管理插件riverpod_repo的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter依赖注入与状态管理插件riverpod_repo的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于在Flutter中使用riverpod_repo
进行依赖注入与状态管理,这里是一个简要的代码示例,展示了如何设置和使用riverpod_repo
。riverpod_repo
是一个结合了riverpod
和freezed
的库,用于更好地管理应用程序的状态和依赖项。
首先,确保在你的pubspec.yaml
文件中添加必要的依赖项:
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^1.0.0 # 请根据最新版本进行调整
riverpod_repo: ^0.1.0 # 请根据最新版本进行调整
freezed_annotation: ^0.15.0 # freezed库用于数据类不可变性
然后,运行flutter pub get
来获取这些依赖项。
接下来,我们创建一个简单的仓库(Repo)并使用riverpod
进行依赖注入。
1. 创建数据模型
使用freezed
创建一个不可变的数据模型。例如,我们有一个简单的用户模型:
// user_model.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user_model.g.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String name,
}) = _User;
}
运行flutter pub run build_runner build
来生成user_model.g.dart
文件。
2. 创建仓库
接下来,我们创建一个仓库来处理用户数据的获取和管理:
// user_repo.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_repo/riverpod_repo.dart';
import 'user_model.dart';
final userProvider = RepoProvider<User>((ref) {
// 这里可以添加数据获取逻辑,例如从API获取用户数据
// 为简单起见,这里我们直接返回一个硬编码的用户对象
return User(id: '1', name: 'John Doe');
});
3. 在UI中使用仓库
现在,我们可以在UI组件中使用userProvider
来获取用户数据:
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'user_repo.dart';
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: UserScreen(),
);
}
}
class UserScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProvider);
return Scaffold(
appBar: AppBar(
title: Text('User Info'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('ID: ${user.id}'),
Text('Name: ${user.name}'),
],
),
),
);
}
}
总结
以上代码展示了如何使用riverpod_repo
在Flutter应用中实现依赖注入和状态管理。通过定义数据模型、创建仓库以及在UI组件中消费仓库提供的数据,我们可以轻松地管理应用的状态和依赖项。
请注意,这只是一个简单的示例。在实际应用中,你可能会需要更复杂的逻辑来处理数据获取、缓存、错误处理等。riverpod_repo
和riverpod
提供了强大的工具来帮助你实现这些功能。