Setting up Provider Architecture for Flutter Applications
Provider is the most popular Flutter package by download count. It wraps InheritedWidget in a convenient API and eliminates the need to manually pass dependencies through the widget tree. For small to medium-sized projects, Provider is a pragmatic choice: minimal boilerplate, maximum readability.
Basic Structure with ChangeNotifier
class ProfileNotifier extends ChangeNotifier {
final UserRepository _repository;
ProfileNotifier(this._repository);
UserProfile? _profile;
bool _isLoading = false;
String? _error;
UserProfile? get profile => _profile;
bool get isLoading => _isLoading;
String? get error => _error;
Future<void> load(String userId) async {
_isLoading = true;
_error = null;
notifyListeners();
try {
_profile = await _repository.getProfile(userId);
} catch (e) {
_error = e.toString();
} finally {
_isLoading = false;
notifyListeners();
}
}
}
Widget tree registration:
MultiProvider(
providers: [
RepositoryProvider(create: (_) => UserRepositoryImpl()),
ChangeNotifierProxyProvider<UserRepositoryImpl, ProfileNotifier>(
create: (ctx) => ProfileNotifier(ctx.read()),
update: (ctx, repo, prev) => prev!..updateRepo(repo),
),
],
child: MyApp(),
)
In a widget: context.watch<ProfileNotifier>() to subscribe to changes, context.read<ProfileNotifier>() to call methods without subscription.
The Main Provider Trap
context.watch() inside build() rebuilds the entire widget on any notifyListeners(). If ProfileNotifier calls notifyListeners() three times during one load — three redraws. Solution: Selector<ProfileNotifier, UserProfile?> subscribes only to a specific field, rebuild only on its change.
Selector<ProfileNotifier, bool>(
selector: (_, notifier) => notifier.isLoading,
builder: (_, isLoading, __) => isLoading
? const CircularProgressIndicator()
: const SizedBox(),
)
When Provider is Sufficient
Provider suits: small application (up to 15–20 screens), 1–2 developers, no complex inter-screen dependencies. For applications with reactive data streams (WebSocket, realtime) or complex navigation — consider Riverpod or BLoC.
What We Configure
MultiProvider at MaterialApp level. Layered structure: repository → notifier → widget. Testing via ProviderContainer without Flutter dependency. Sample screen as template for the team.
Timeline
Setting up Provider architecture: 1–2 days. Cost — after requirements analysis.







