# Future Provider Package
`future_provider` is a Flutter package designed to help developers handle asynchronous operations with ease. It allows you to execute multiple asynchronous tasks, handle success/failure responses, manage loading states, and retry failed tasks with a clean and modular approach.
## Features
- Sequential execution of multiple asynchronous tasks.
- Handles loading states and provides progress feedback.
- Supports retries for failed tasks with a configurable retry limit.
- Built-in success and failure handlers.
- Lightweight and easy-to-use API.
## Getting Started
To use the `future_provider` package in your Flutter project, follow these steps:
### Step 1: Add Dependency
Add the following dependency to your `pubspec.yaml`:
```yaml
dependencies:
future_provider: ^1.0.0
Then, run:
flutter pub get
Step 2: Import the Package
Import the future_provider package in the Dart file where you want to use it:
import 'package:future_provider/future_provider.dart';
Class: FutureProvider
The FutureProvider class is the core of the package. It is designed to manage asynchronous operations by executing tasks sequentially and handling various states like loading, success, and failure.
Constructor
FutureProvider(BuildContext context);
Parameters:
context: TheBuildContextused for showing progress indicators and managing dialogs.
Methods
void init()
Initializes the process by loading the processes and setting up the necessary state.
void _start({bool diable=false})
Starts the process. If diable is true, it shows a loading dialog.
void _stop({bool diable=false})
Stops the ongoing process. If diable is true, it hides the loading dialog.
void executeSingleProcess(...)
Executes a single process. This method runs a specific process and handles its result or failure.
Parameters:
enableLoadIndicator: Whether to show the loading indicator while the process is running.onExecuted: A callback that is called after the process has been executed.onFailed: A callback that is called if the process fails.
void executeAll(...)
Executes all processes in sequence. It handles the execution of multiple processes and provides feedback after each task.
void resetProcess()
Resets the process state, clearing any ongoing tasks and results.
bool get isAllProcessCompleted
Checks if all processes have been completed.
How to Use
Example.dart
class Example extends FutureProvider {
Example(super.context);
Future<String> getData() async {
await Future.delayed(const Duration(seconds: 1));
return "{DATA}";
}
@override
FutureProcess loadProcess() => FutureProcess({
"get_data": getData,
});
@override
void onSucess(FutureData data) {
// print(data.futureData);
}
}
Home.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:future/main.dart';
import 'package:future/mylib/future_event.dart';
import 'package:future/mylib/future_process.dart';
import 'package:future/services/api_service.dart';
class Home extends StatefulWidget {
const Home({super.key});
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late Example service = Example(context);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ElevetedButton(
onPressed: (){
service.executeAll();
},
child: Center(child: Text("Load")),
),
);
}
}
Class: FutureProcess
The FutureProcess class holds a map of processes (each represented as a Future function) and provides methods to find, execute, and manage these processes.
Constructor
FutureProcess(Map<String, Future Function()> proccessList);
Parameters:
proccessList: A map where the key is a string ID for each process, and the value is aFuturefunction.
Methods
Future Function() findById(String id)
Finds and returns a Future function by its ID.
Future Function() findByIndex(int idx)
Finds and returns a Future function by its index in the list.
int findIndexById(String id)
Finds and returns the index of a process by its ID.
Class: FutureData
The FutureData class holds the results of the executed asynchronous tasks in a list.
Constructor
FutureData();
Properties
futureData: A list where the results of the executed tasks are stored.
Class: FutureWidget
FutureWidget is a customizable widget that allows you to display asynchronous data with loading states, retries, and failure handling.
Constructor
FutureWidget({
required this.process,
required this.builder,
this.canBuild=true,
this.loadingIndicator,
this.withAnimation=false,
this.canExecuteProcess=true,
this.reTryTime=1,
this.canReTry=false,
this.onSucess,
});
Parameters:
process: TheFutureProcessthat holds the processes to execute.builder: A callback that builds the widget once the process is completed.loadingIndicator: A custom widget to display while loading.canReTry: Whether the widget should retry failed tasks.reTryTime: The number of retries before giving up.
Example Usage
FutureWidget(
process: myProcess, // An instance of FutureProcess
builder: (context, data) {
return Text('Process Completed!');
},
loadingIndicator: CircularProgressIndicator(),
onSucess: () {
print('Process Successful!');
},
);
Example
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:future/mylib/future_process.dart';
import 'package:future/mylib/future_widget.dart';
class RetryExample extends StatelessWidget {
const RetryExample({super.key});
Future<Map<String, dynamic>> getUserProfile() async {
await Future.delayed(Duration(seconds: 2));
return {"name": "John Doe", "age": 25};
}
Future<List<String>> getUserPosts() async {
await Future.delayed(Duration(seconds: 2));
return ["Hello World!", "Flutter is awesome!", "FutureWidget Testing"];
}
Future<List<String>> getUserFollowers() async {
await Future.delayed(Duration(seconds: 2));
if (Random().nextBool()) {
throw Exception("Followers fetch failed");
}
return ["Alice", "Bob", "Charlie"];
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureWidget(
process: FutureProcess({
"getUserProfile": getUserProfile,
"getUserPosts": getUserPosts,
"getUserFollowers": getUserFollowers,
}),
canReTry: true,
reTryTime: 3, // Retry 3 times before failing
builder: (context, data) {
final user = data.futureData[0];
final posts = data.futureData[1];
final followers = data.futureData[2];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("[User: ${user['name']}, Age: ${user['age']}]"),
for (int i = 0; i < posts.length; i++) Text("Post ${i + 1}: ${posts[i]}"),
if (followers == null)
Column(
children: [
Icon(Icons.error, color: Colors.red),
Text("❌ Failed to Load Data"),
],
)
else
Column(
children: [
Text("Data"),
],
),
],
);
},
),
),
);
}
}
Class: FutureList
FutureList is a widget designed for executing multiple processes in sequence and displaying the results. It handles success and failure at each step, and allows for retrying failed tasks.
Constructor
FutureList({
required this.process,
required this.childern,
required this.mainContext,
this.showLog = true,
});
Parameters:
process: TheFutureProcessobject containing the list of tasks to execute.childern: A list ofListBuilderobjects that define how to build widgets before and after each task.showLog: Whether to show debug logs.
Example Usage
FutureList(
process: myProcess, // An instance of FutureProcess
childern: [
ListBuilder(
builder: (data) {
return Text('First Process Completed');
},
beforeLoadWidget: () => CircularProgressIndicator(),
),
// More ListBuilder items...
],
mainContext: context,
);
Example
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:future/mylib/future_list.dart';
import 'package:future/mylib/future_process.dart';
class FutureListTest extends StatefulWidget {
@override
_FutureListTestState createState() => _FutureListTestState();
}
class _FutureListTestState extends State<FutureListTest> {
Future<String> fetchUserProfile() async {
await Future.delayed(Duration(seconds: 2));
if (Random().nextBool()) throw Exception("Profile Fetch Failed");
return "User: John Doe, Age: 25";
}
Future<List<String>> fetchUserPosts() async {
await Future.delayed(Duration(seconds: 3));
if (Random().nextBool()) throw Exception("Posts Fetch Failed");
return ["Post 1: Hello World!", "Post 2: Flutter is awesome!", "Post 3: FutureList Testing"];
}
Future<List<String>> fetchUserFollowers() async {
await Future.delayed(Duration(seconds: 2));
if (Random().nextBool()) throw Exception("Followers Fetch Failed");
return ["Alice", "Bob", "Charlie", "David"];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("FutureList Complex Test")),
body: FutureList(
mainContext: context,
process: FutureProcess({
'fetch_profile': fetchUserProfile,
'fetch_posts': fetchUserPosts,
'fetch_followers': fetchUserFollowers,
}),
childern: [
// Profile Fetch
ListBuilder(
onFailDisplayWidget: () => Center(
child: Column(
children: [
Text("❌ Failed to Load Profile"),
ElevatedButton(
onPressed: () => setState(() {}),
child: Text("Retry"),
),
],
),
),
builder: (data) => ListTile(
leading: Icon(Icons.person, size: 50),
title: Text(data.futureData.toString(), style: TextStyle(fontSize: 18)),
),
),
// Posts Fetch
ListBuilder(
onFailDisplayWidget: () => Center(
child: Column(
children: [
Text("❌ Failed to Load Posts"),
ElevatedButton(
onPressed: () => setState(() {}),
child: Text("Retry"),
),
],
),
),
builder: (data) => Column(
children: (data.futureData.first as List<String>)
.map((post) => ListTile(title: Text(post)))
.toList(),
),
),
// Followers Fetch
ListBuilder(
onFailDisplayWidget: () => Center(
child: Column(
children: [
Text("❌ Failed to Load Followers"),
ElevatedButton(
onPressed: () => setState(() {}),
child: Text("Retry"),
),
],
),
),
// builder: (data) => Text("Loaded ${data.futureData}"),
builder: (data) => Wrap(
children: (data.futureData.first as List<String>)
.map((follower) => Chip(label: Text(follower)))
.toList(),
),
),
],
),
);
}
}
Additional Information
Contributing
To contribute to this package, fork the repository and submit a pull request with your changes.
Issues
If you encounter any issues or have any feature requests, please open an issue on the repository.
License
This package is licensed under the MIT License. See the LICENSE file for more information.