State Management
The app uses the Provider pattern for state management.
Providers
AuthProvider
Manages user authentication state.
State:
phoneNumber- User's phone numberisVerified- Authentication statususerRole- Current user role (PROVIDER/SERVICE_SEEKER)userData- User profile dataisLoading- Loading stateerrorMessage- Error messages
Methods:
sendOTP(phone, role)- Request OTPverifyOTP(code)- Verify OTP codesignOut()- Sign out userinitialize()- Load saved session
LocationProvider
Manages location services and tracking.
JobProvider (if exists)
Manages job-related state.
Usage Patterns
Reading State
// Using Consumer (rebuilds on changes)
Consumer<AuthProvider>(
builder: (context, authProvider, child) {
return Text(authProvider.phoneNumber ?? 'Not logged in');
},
)
// Using Provider.of (one-time read)
final authProvider = Provider.of<AuthProvider>(context, listen: false);
final phone = authProvider.phoneNumber;
Updating State
final authProvider = Provider.of<AuthProvider>(context, listen: false);
authProvider.setPhoneNumber('+264812345678');
Listening to State Changes
// Consumer automatically rebuilds when state changes
Consumer<AuthProvider>(
builder: (context, authProvider, child) {
if (authProvider.isLoading) {
return CircularProgressIndicator();
}
return YourWidget();
},
)
Best Practices
- Use
listen: falsewhen you only need to call methods, not read state - Use Consumer when UI needs to react to state changes
- Minimize provider scope - only wrap widgets that need the provider
- Separate providers for different concerns
- Handle loading and error states in providers
Local State vs Global State
- Global State (Provider): User authentication, app settings, shared data
- Local State (setState): UI-only state like form inputs, animations