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

Popular posts from this blog

Unlocking the Power of OOP: A Beginner's Guide to Objects, Encapsulation, Inheritance, Abstraction, and Polymorphism

HTTP GET Response in Flutter

Building a Flutter Firebase Firestore CRUD App