Flutter Provider: FutureProvider vs ChangeNotifierProvider vs StreamProvider for API Calls
Flutter Provider: FutureProvider vs ChangeNotifierProvider vs StreamProvider for API Calls
State management is crucial in Flutter apps, especially when handling API calls. In this post, we will explore FutureProvider for automatic API fetching, ChangeNotifierProvider for manual control, and StreamProvider for real-time data updates.
1. Using FutureProvider for Automatic API Calls
FutureProvider is useful when you want to fetch data once and automatically update the UI when the data is received.
Example: Fetching Posts from an API Using FutureProvider
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(
FutureProvider<List<dynamic>>(
create: (context) => fetchPosts(),
initialData: [],
child: MyApp(),
),
);
}
Future<List<dynamic>> fetchPosts() async {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception("Failed to load posts");
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final posts = Provider.of<List<dynamic>>(context);
return Scaffold(
appBar: AppBar(title: Text("API Call with FutureProvider")),
body: posts.isEmpty
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post['title']),
subtitle: Text(post['body']),
);
},
),
);
}
}
2. Using ChangeNotifierProvider for Manual API Calls
If you want manual control over API calls (e.g., refreshing data with a button), use ChangeNotifierProvider.
Example: Manual API Fetching with ChangeNotifier
class PostProvider with ChangeNotifier {
List<dynamic> _posts = [];
bool _isLoading = false;
List<dynamic> get posts => _posts;
bool get isLoading => _isLoading;
Future<void> fetchPosts() async {
_isLoading = true;
notifyListeners();
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
_posts = jsonDecode(response.body);
}
_isLoading = false;
notifyListeners();
}
}
When to Use ChangeNotifierProvider?
✅ When you need manual refresh control. ✅ When API data updates frequently. ✅ When you need better control over state
3. Using StreamProvider for Real-Time API Calls
StreamProvider is useful when you need continuous real-time updates, such as live stock prices or chat messages.
Example: Streaming Real-Time Data Using StreamProvider
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(
StreamProvider<List<dynamic>>(
create: (context) => streamPosts(),
initialData: [],
child: MyApp(),
),
);
}
Stream<List<dynamic>> streamPosts() async* {
while (true) {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
yield jsonDecode(response.body);
}
await Future.delayed(Duration(seconds: 5)); // Fetch every 5 seconds
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final posts = Provider.of<List<dynamic>>(context);
return Scaffold(
appBar: AppBar(title: Text("Real-Time Data with StreamProvider")),
body: posts.isEmpty
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post['title']),
subtitle: Text(post['body']),
);
},
),
);
}
}
When to Use StreamProvider?
✅ When data updates frequently in real-time. ✅ When you need continuous API calls without manual refresh. ✅ When you are working with live data feeds.
Final Thoughts
Use FutureProvider when you need automatic API fetching.
Use ChangeNotifierProvider when you need manual control and refresh.
Use StreamProvider when you need real-time data updates.
Now that you know the difference, which one will you use? 🚀
Comments
Post a Comment