Tillitsdone
down Scroll to discover

Implement Dependency Injection in Flutter Provider

Learn how to effectively implement dependency injection in Flutter using Provider package.

Discover best practices, practical examples, and testing strategies for better app architecture.
thumbnail

A modern minimalist architectural structure with clean lines and geometric shapes featuring sage green and white elements against a bright blue sky shot from a low angle perspective with dramatic lighting high-quality ultra-realistic cinematic 8K UHD high resolution sharp and detail

Implementing Dependency Injection in Flutter with Provider

If you’ve been developing Flutter applications, you’ve probably encountered scenarios where managing state and dependencies becomes increasingly complex as your app grows. Today, let’s dive into how we can implement dependency injection in Flutter using the Provider package – a clean and efficient solution that’ll make your code more maintainable and testable.

Understanding Dependency Injection

Dependency injection might sound intimidating, but it’s actually a straightforward concept. Instead of creating dependencies inside your classes, you inject them from the outside. This makes your code more flexible and easier to test.

An abstract composition of floating geometric shapes in bright orange and navy blue arranged in a balanced pattern against a light gray background captured from a bird's eye view high-quality ultra-realistic cinematic 8K UHD high resolution sharp and detail

Why Provider for Dependency Injection?

Provider is a state management solution that also excellently serves as a dependency injection tool. It’s lightweight, easy to understand, and officially recommended by the Flutter team. Here’s why it’s fantastic for dependency injection:

  • Simplified object creation and sharing
  • Automatic disposal of resources
  • Great integration with Flutter’s widget tree
  • Built-in support for dependency overriding in tests

Setting Up Provider

First, let’s set up our project with Provider. Add the following to your pubspec.yaml:

dependencies:
provider: ^6.0.5

Implementing Dependency Injection

Let’s walk through a practical example. Imagine we’re building a weather app that needs to inject an API service and a location service.

// Weather service
class WeatherService {
Future<String> getWeatherData() async {
// API call implementation
return 'Sunny';
}
}
// Location service
class LocationService {
Future<String> getCurrentLocation() async {
// Location implementation
return 'New York';
}
}
// Weather repository that depends on both services
class WeatherRepository {
final WeatherService weatherService;
final LocationService locationService;
WeatherRepository({
required this.weatherService,
required this.locationService,
});
Future<String> getLocalWeather() async {
final location = await locationService.getCurrentLocation();
final weather = await weatherService.getWeatherData();
return '$weather in $location';
}
}

A serene cityscape with modern buildings under a bright yellow and blue gradient sky soft clouds catching golden hour light viewed from a straight-on perspective high-quality ultra-realistic cinematic 8K UHD high resolution sharp and detail

Setting Up the Provider Tree

Now, let’s set up our dependency injection using Provider:

void main() {
runApp(
MultiProvider(
providers: [
Provider(create: (_) => WeatherService()),
Provider(create: (_) => LocationService()),
ProxyProvider2<WeatherService, LocationService, WeatherRepository>(
update: (_, weatherService, locationService, __) => WeatherRepository(
weatherService: weatherService,
locationService: locationService,
),
),
],
child: MyApp(),
),
);
}

Using the Injected Dependencies

Access your dependencies anywhere in the widget tree:

class WeatherWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get the repository instance
final repository = context.read<WeatherRepository>();
return FutureBuilder<String>(
future: repository.getLocalWeather(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!);
}
return CircularProgressIndicator();
},
);
}
}

Best Practices and Tips

  1. Keep providers at the highest necessary level in the widget tree
  2. Use ProxyProvider for dependencies that depend on other providers
  3. Prefer context.read() for one-time access and context.watch() for reactive updates
  4. Create interfaces for your services to make testing easier

Testing with Provider

Provider makes testing a breeze. You can easily override dependencies:

testWidgets('Weather widget test', (tester) async {
await tester.pumpWidget(
MultiProvider(
providers: [
Provider<WeatherService>(
create: (_) => MockWeatherService(),
),
Provider<LocationService>(
create: (_) => MockLocationService(),
),
],
child: MyApp(),
),
);
});

Conclusion

Dependency injection with Provider in Flutter is a powerful pattern that can significantly improve your code’s maintainability and testability. It might take some time to get used to, but the benefits are well worth the initial learning curve.

An elegant abstract pattern of interconnected geometric shapes in sage green and gray tones floating against a pristine white background photographed from a top-down perspective high-quality ultra-realistic cinematic 8K UHD high resolution sharp and detail

icons/logo-tid.svgicons/flutter.svg

Talk with CEO

Ready to bring your web/app to life or boost your team with expert Thai developers?
Contact us today to discuss your needs, and let’s create tailored solutions to achieve your goals. We’re here to help at every step!
🖐️ Contact us
Let's keep in Touch
Thank you for your interest in Tillitsdone! Whether you have a question about our services, want to discuss a potential project, or simply want to say hello, we're here and ready to assist you.
We'll be right here with you every step of the way.
Contact Information
rick@tillitsdone.com+66824564755
Find All the Ways to Get in Touch with Tillitsdone - We're Just a Click, Call, or Message Away. We'll Be Right Here, Ready to Respond and Start a Conversation About Your Needs.
Address
9 Phahonyothin Rd, Khlong Nueng, Khlong Luang District, Pathum Thani, Bangkok Thailand
Visit Tillitsdone at Our Physical Location - We'd Love to Welcome You to Our Creative Space. We'll Be Right Here, Ready to Show You Around and Discuss Your Ideas in Person.
Social media
Connect with Tillitsdone on Various Social Platforms - Stay Updated and Engage with Our Latest Projects and Insights. We'll Be Right Here, Sharing Our Journey and Ready to Interact with You.
We anticipate your communication and look forward to discussing how we can contribute to your business's success.
We'll be here, prepared to commence this promising collaboration.
Frequently Asked Questions
Explore frequently asked questions about our products and services.
Whether you're curious about features, warranties, or shopping policies, we provide comprehensive answers to assist you.