Для внедрения flutter_riverpod 2.0 для управления состоянием в проекте на Flutter с использованием clean architecture, выполните следующие шаги:
1. Установка зависимостей
В pubspec.yaml
добавьте зависимость flutter_riverpod
:
dependencies:
flutter_riverpod: ^2.0.0 # Проверьте последнюю версию
Запустите команду flutter pub get
, чтобы установить зависимости.
2. Структура проекта с чистой архитектурой
Ваш проект должен следовать принципам чистой архитектуры с такой структурой:
- domain: содержит сущности, юзкейсы и интерфейсы репозиториев.
- data: реализует репозитории, API-клиенты и другие источники данных.
- presentation: содержит UI-код, view models и логику управления состоянием.
3. Настройка провайдеров для юзкейсов и репозиториев
Шаг 1: Репозиторий
Создайте репозиторий для получения данных, который будет использоваться в слое domain:
class UserRepository {
Future<User> getUserData() async {
// Логика для получения данных пользователя (например, из API или локальной базы данных)
return User(name: "John Doe", age: 30);
}
}
final userRepositoryProvider = Provider<UserRepository>((ref) {
return UserRepository();
});
Шаг 2: Юзкейс
Юзкейсы содержат бизнес-логику и взаимодействуют с репозиториями:
class GetUserDataUseCase {
final UserRepository repository;
GetUserDataUseCase(this.repository);
Future<User> call() async {
return await repository.getUserData();
}
}
final getUserDataUseCaseProvider = Provider<GetUserDataUseCase>((ref) {
final repository = ref.watch(userRepositoryProvider);
return GetUserDataUseCase(repository);
});
4. Управление состоянием с помощью Notifier
Используйте Notifier
для управления состоянием, чтобы упростить логику.
class UserNotifier extends Notifier<User?> {
final GetUserDataUseCase getUserDataUseCase;
UserNotifier(this.getUserDataUseCase);
@override
User? build() {
return null; // Начальное состояние: нет данных
}
Future<void> loadUser() async {
state = await getUserDataUseCase(); // Получение данных и обновление состояния
}
void clearUser() {
state = null; // Очистка состояния
}
}
final userNotifierProvider = NotifierProvider<UserNotifier, User?>((ref) {
final getUserDataUseCase = ref.watch(getUserDataUseCaseProvider);
return UserNotifier(getUserDataUseCase);
});
5. Использование провайдеров в UI
Использование Notifier
в UI
class UserScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userNotifierProvider);
return Scaffold(
appBar: AppBar(
title: Text('User Info'),
),
body: Center(
child: user == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('No user loaded'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ref.read(userNotifierProvider.notifier).loadUser();
},
child: Text('Load User'),
),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Name: ${user.name}, Age: ${user.age}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
ref.read(userNotifierProvider.notifier).clearUser();
},
child: Text('Clear User'),
),
],
),
),
);
}
}
6. Оберните ваше приложение в ProviderScope
В файле main.dart
оберните приложение с помощью ProviderScope
:
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: UserScreen(),
);
}
}
Заключение:
- ProviderScope: Необходим для включения управления состоянием с помощью Riverpod во всем приложении.
- Notifier: Управляет изменениями состояния более просто и удобно по сравнению с
StateNotifier (использовался в более старых версиях flutter_riverpod)
, что подходит для более простых сценариев. - Разделение ответственности: В соответствии с чистой архитектурой, репозиторий и юзкейсы отделены от UI, что делает код более поддерживаемым и тестируемым.
Посмотреть подходящие вакансии для Flutter-разработчика можно тут!