Готовый каркас Flutter приложения с Clean Architecture, настроенными инструментами разработки и современным стеком технологий для быстрого старта новых проектов.
# Основное приложение с Device Preview
flutter run -d windows
# Или на любой другой платформе
flutter run -d chrome
flutter run -d android # при наличии эмулятора# Для разработки UI компонентов изолированно
flutter run widgetbook/main.dart -d windows# Все тесты
flutter test
# Только unit тесты
flutter test test/features/presentation/cubit/theme_cubit_test.dart
# С покрытием
flutter test --coverage# Одноразово
dart run build_runner build --delete-conflicting-outputs
# С отслеживанием изменений
dart run build_runner watch- Device Preview - переключайте устройства прямо в приложении (справа в панели)
- Widgetbook - разрабатывайте компоненты изолированно, тестируйте разные состояния
- Настройки темы - в приложении Settings → Theme (Light/Dark/System)
- Добавление фич - следуйте структуре Clean Architecture в папке
features/
- Flutter SDK 3.27.0 или выше
- Dart 3.0.0 или выше
- Visual Studio (для Windows)
- Android Studio (опционально)
- Клонируйте репозиторий и установите зависимости:
git clone <repository-url>
cd clean_architecture_application_framework
flutter pub get- Генерация кода:
dart run build_runner build --delete-conflicting-outputs- Запуск основного приложения:
# На Windows
flutter run -d windows
# На Android (при наличии эмулятора)
flutter run -d android
# На Web
flutter run -d chrome- Запуск Widgetbook для разработки компонентов:
flutter run widgetbook/main.dart -d windowsWidgetbook позволяет изолированно разрабатывать и тестировать UI компоненты:
- Запустите Widgetbook:
flutter run widgetbook/main.dart -d windows- В интерфейсе Widgetbook:
- Выберите компонент в левой панели
- Тестируйте разные состояния и параметры
- Переключайтесь между темами (Light/Dark)
- Эмулируйте разные устройства
Приложение включает Device Preview для тестирования на разных устройствах:
- 📱 iPhone SE, iPhone 13
- 📱 Samsung Galaxy S20
- 📱 Различные Android устройства
Переключайтесь между устройствами прямо в приложении!
Запуск всех тестов:
flutter testЗапуск с покрытием:
flutter test --coverageПроект следует принципам Clean Architecture с разделением на 3 основных слоя:
lib/
├── 🎯 features/ # Бизнес-функциональность
│ ├── 📊 data/ # Слой данных
│ │ ├── datasources/ # Источники данных (API, Local)
│ │ ├── models/ # Модели данных
│ │ └── repositories/ # Реализация репозиториев
│ ├── 💼 domain/ # Бизнес-логика
│ │ ├── entities/ # Сущности предметной области
│ │ ├── repositories/ # Контракты репозиториев
│ │ └── usecases/ # Варианты использования
│ └── 🎨 presentation/ # UI слой
│ ├── cubit/ # Управление состоянием
│ └── screens/ # Экраны приложения
├── ⚙️ core/ # Общие компоненты
│ ├── di/ # Dependency Injection
│ ├── router/ # Навигация
│ └── usecases/ # Базовые UseCase
└── 📱 main.dart # Точка входа
widgetbook/ # 📚 Каталог компонентов
test/ # 🧪 Тесты
- Clean Architecture - Разделение ответственности
- BLoC (Cubit) - Управление состоянием
- GetIt + Injectable - Dependency Injection
- Auto Route - Декларативная маршрутизация
- Material 3 - Современный дизайн
- Device Preview - Эмуляция устройств
- Widgetbook - Каталог UI компонентов
- Freezed - Immutable классы
- Build Runner - Генерация кода
- Dio - HTTP клиент
- Shared Preferences - Локальное хранение
- JSON Serialization - Сериализация данных
// lib/features/domain/entities/my_entity.dart
@freezed
class MyEntity with _$MyEntity {
const factory MyEntity({
required String id,
required String name,
}) = _MyEntity;
}
// lib/features/domain/repositories/my_repository.dart
abstract class MyRepository {
Future<List<MyEntity>> getItems();
}
// lib/features/domain/usecases/get_items_usecase.dart
@injectable
class GetItemsUseCase implements UseCase<List<MyEntity>, NoParams> {
final MyRepository _repository;
GetItemsUseCase(this._repository);
@override
Future<List<MyEntity>> call(NoParams params) async {
return await _repository.getItems();
}
}// lib/features/data/models/my_model.dart
@freezed
class MyModel with _$MyModel {
const factory MyModel({
required String id,
required String name,
}) = _MyModel;
factory MyModel.fromJson(Map<String, dynamic> json) =>
_$MyModelFromJson(json);
}
// Добавьте extension методы для конвертации между Entity и Model// lib/features/presentation/cubit/my_cubit.dart
@injectable
class MyCubit extends Cubit<MyState> {
final GetItemsUseCase _getItemsUseCase;
MyCubit(this._getItemsUseCase) : super(const MyState.initial());
Future<void> loadItems() async {
emit(const MyState.loading());
try {
final items = await _getItemsUseCase(NoParams());
emit(MyState.loaded(items));
} catch (e) {
emit(MyState.error(e.toString()));
}
}
}
// lib/features/presentation/screens/my_screen.dart
@RoutePage()
class MyScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => getIt<MyCubit>()..loadItems(),
child: Scaffold(
appBar: AppBar(title: const Text('My Screen')),
body: BlocBuilder<MyCubit, MyState>(
builder: (context, state) {
return state.when(
initial: () => const SizedBox(),
loading: () => const CircularProgressIndicator(),
loaded: (items) => ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(items[index].name));
},
),
error: (message) => Text('Error: $message'),
);
},
),
),
);
}
}// lib/core/router/app_router.dart
@AutoRouterConfig(replaceInRouteName: 'Screen,Route')
class AppRouter extends _$AppRouter {
@override
List<AutoRoute> get routes => [
// ... существующие маршруты
AutoRoute(
page: MyRoute.page,
path: '/my-screen',
),
];
}dart run build_runner build --delete-conflicting-outputs// widgetbook/main.dart
WidgetbookComponent(
name: 'MyScreen',
useCases: [
WidgetbookUseCase(
name: 'Default',
builder: (context) => const MyScreen(),
),
WidgetbookUseCase(
name: 'Loading State',
builder: (context) => const MyScreenLoading(),
),
],
),# Одноразовая генерация
dart run build_runner build --delete-conflicting-outputs
# Отслеживание изменений
dart run build_runner watch --delete-conflicting-outputs# Все тесты
flutter test
# Тесты с покрытием
flutter test --coverage
# Специфический тест
flutter test test/widget_test.dart# Анализ кода
flutter analyze
# Форматирование
dart format lib/ test/ widgetbook/Темы настраиваются в lib/main.dart:
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue, // Измените основной цвет
),
),Переключение темы доступно в настройках приложения.
- Форкните репозиторий
- Создайте feature branch (
git checkout -b feature/amazing-feature) - Зафиксируйте изменения (
git commit -m 'Add amazing feature') - Отправьте в branch (
git push origin feature/amazing-feature) - Откройте Pull Request
Этот проект распространяется под лицензией MIT. См. файл LICENSE для подробностей.
Готов к использованию! 🚀 Этот каркас предоставляет все необходимое для быстрого старта разработки Flutter приложений с современной архитектурой и инструментами.