Profile Feature Refactoring
Clean Architecture Implementation with BLoC Pattern
This refactoring implements Clean Architecture and BLoC pattern for the Profile feature. The implementation follows these key principles:
1. Layered Architecture
The code is organized into the following layers:
- Presentation Layer: UI components, BLoC implementation
- Domain Layer: Use cases, repository interfaces
- Data Layer: Repository implementations, data sources
2. Directory Structure
lib/
├── features/
│ └── profile/
│ ├── data/
│ │ └── repositories/
│ │ └── profile_repository_impl.dart
│ ├── domain/
│ │ ├── repositories/
│ │ │ └── profile_repository.dart
│ │ └── usecases/
│ │ ├── get_current_user.dart
│ │ ├── update_profile_picture.dart
│ │ └── logout_user.dart
│ ├── presentation/
│ │ ├── bloc/
│ │ │ ├── profile_bloc.dart
│ │ │ ├── profile_event.dart
│ │ │ └── profile_state.dart
│ │ ├── pages/
│ │ │ └── profile_page.dart
│ │ └── widgets/
│ │ ├── profile_header.dart
│ │ ├── profile_info.dart
│ │ └── profile_buttons.dart
│ └── di/
│ └── profile_dependencies.dart
└── navigation/
└── profile.dart
3. BLoC Pattern Implementation
The BLoC (Business Logic Component) pattern separates the presentation layer from the business logic:
- Events: User actions that trigger state changes
- States: Different UI states of the profile feature
- BLoC: Handles events and emits states
4. Dependency Injection
Uses GetIt service locator for dependency injection to provide:
- Repository instances
- Use cases
- BLoC instances
5. Key Benefits
- Separation of Concerns: Each component has a single responsibility
- Testability: Each layer can be tested independently
- Maintainability: Code is more organized and easier to understand
- Scalability: New features can be added with minimal changes to existing code
6. Usage
The profile feature now uses the BLoC pattern for state management. The UI components observe the state changes and update accordingly.
To integrate with the rest of the app, the profile dependencies are initialized in the main.dart file.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await di.init();
// ... other initializations
await initProfileDependencies(); // Initialize profile dependencies
runApp(LiftTrackApp());
}
The navigation component is also updated to provide the BLoC instances to the profile page:
class ProfileScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: getProfileProviders(),
child: const ProfilePage(),
);
}
}