Overview
App Courier follows a clean, layered architecture pattern built with Flutter. The app uses the Provider pattern for state management and separates concerns into distinct layers: UI (screens), business logic (providers), data access (services), and data models.Architecture Layers
Key Design Patterns
1. Provider Pattern
The app uses Flutter’s Provider package for state management. All providers extendChangeNotifier and notify listeners when state changes.
Example from main.dart:
2. Service Layer Pattern
Each domain (customers, encomiendas, etc.) has a dedicated service class that handles API communication. Services receive anApiClient instance via dependency injection.
3. Repository Pattern
Providers act as repositories, managing state and coordinating between the UI and services:Application Initialization
The app initializes inmain.dart following this sequence:
Routing Strategy
The app uses named routes defined inAppRoutes class:
API Communication
All HTTP requests go through the centralizedApiClient class:
- Base URL:
https://api.eisegmi.facturador.es - Authentication: JWT tokens stored in SharedPreferences
- Interceptors: Automatic token injection and 401 handling
- Timeout: 20 seconds for both connect and receive
Module Structure
The app supports three user types, each with dedicated modules:1. Admin Module
- Customer management (CRUD operations)
- Encomienda creation and tracking
- User management
- Dashboard with statistics
2. Client Module
- Request shipping services
- Track encomiendas
- View solicitud history
3. Motorizado (Driver) Module
- View assigned encomiendas
- Update encomienda status
- Upload delivery photos
Error Handling
Error handling follows a consistent pattern across the app:Key Architectural Decisions
Why Provider over other state management solutions?
Why Provider over other state management solutions?
Provider was chosen for its simplicity, official Flutter team support, and sufficient capabilities for the app’s requirements. It integrates well with Flutter’s widget tree and has minimal boilerplate.
Why separate Service and Provider layers?
Why separate Service and Provider layers?
Separating services from providers follows the Single Responsibility Principle:
- Services: Handle API communication and data transformation
- Providers: Manage state, loading states, and coordinate UI updates
Why single ApiClient instance?
Why single ApiClient instance?
A singleton ApiClient ensures:
- Consistent configuration across all services
- Shared interceptors for authentication
- Efficient connection pooling
- Centralized request/response logging
Next Steps
- Learn about State Management patterns
- Explore the Folder Structure
- Review Services Architecture