https://github.com/mahmoud-saeed-mahmoud/loading_state_handler
The StateHandlerWidget manages different UI states—loading, error, empty, and normal—allowing you to customize the displayed widgets for each state.
https://github.com/mahmoud-saeed-mahmoud/loading_state_handler
dart data error flutter flutter-package flutter-widget loading state
Last synced: 4 months ago
JSON representation
The StateHandlerWidget manages different UI states—loading, error, empty, and normal—allowing you to customize the displayed widgets for each state.
- Host: GitHub
- URL: https://github.com/mahmoud-saeed-mahmoud/loading_state_handler
- Owner: Mahmoud-Saeed-Mahmoud
- License: mit
- Created: 2024-10-27T14:34:15.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-29T16:19:42.000Z (about 1 year ago)
- Last Synced: 2025-10-12T10:07:24.610Z (8 months ago)
- Topics: dart, data, error, flutter, flutter-package, flutter-widget, loading, state
- Language: Dart
- Homepage: https://mahmoud-saeed-mahmoud.github.io/loading_state_handler/
- Size: 802 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# LoadingStateHandlerWidget
[](https://dart.dev) [](https://dart.dev) [](https://pub.dev/packages/loading_state_handler) [](https://img.shields.io/pub/likes/loading_state_handler) [](https://img.shields.io/pub/publisher/loading_state_handler)   [](/LICENSE)
A powerful Flutter widget for managing UI states with built-in retry functionality. This widget handles loading, error, empty, and normal states elegantly while providing a customizable retry mechanism with cooldown support.
## Features
- 🔄 Smart state management (loading, error, empty, normal, data)
- ⏲️ Built-in retry mechanism with configurable cooldown
- 🎨 Fully customizable widgets for each state
- 🌐 Global default configurations
- ⚡ Optimized performance with const constructor
- 🎯 Type-safe callbacks and builders
## Installation
Run the following command to add the package to your project:
```bash
flutter pub add loading_state_handler
```
or add the package to your `pubspec.yaml` file:
```yml
dependencies:
loading_state_handler: ^2.1.0
```
## Quick Start
```dart
// Set global defaults (optional)
LoadingStateHandlerWidget.setDefaults(
defaultRetryCooldown: const Duration(seconds: 5),
defaultErrorBuilder:
(context, errorMessage, retryWidget, retryCooldown, onRetry) => Center(
child: Column(
spacing: 20,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(errorMessage ?? 'An error occurred'),
retryWidget,
],
),
),
);
// Use in your widget
LoadingStateHandlerWidget(
currentState: currentState,
onLoading: (defaultOnLoading, context, message) {
/// Uncomment to use the default loading callback
// defaultOnLoading?.call(context, message);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Custom Loading...'),
),
);
},
onData: (defaultOnData, context, message) {
defaultOnData?.call(context, message);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Custom Got Data...'),
),
);
},
errorMessage: errorMessage,
child: const Center(child: Text('Data Loaded Successfully!')),
);
```
## Advanced Usage
### Retry Mechanism
The widget includes a sophisticated retry mechanism with cooldown:
```dart
LoadingStateHandlerWidget(
// State control properties
currentState: _currentState,
// Custom messages for different states
errorMessage: _errorMessage,
emptyMessage: 'No data available',
loadingMessage: 'Fetching data...',
// Retry configuration
enableRetry: true, // Enable the retry mechanism
retryCooldown:
const Duration(seconds: 3), // Custom cooldown per instance
onRetry: () {
// Callback executed when the retry button is pressed
// This will be disabled during the cooldown period
_fetchData();
},
// Content to display when in normal state (not loading/error/empty)
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Data loaded successfully!',
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _fetchData,
child: const Text('Refresh Data'),
),
],
),
),
);
```
### Global Configuration
Set default behaviors for all instances:
```dart
LoadingStateHandlerWidget.setDefaults(
defaultOnData: (context, message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Default Got Data...'),
),
);
},
defaultOnLoading: (context, message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Default Loading...'),
),
);
},
defaultLoadingBuilder: (context, loadingMessage) =>
const Center(child: CircularProgressIndicator()),
defaultErrorBuilder:
(context, errorMessage, retryWidget, retryCooldown, onRetry) => Center(
child: Text(
'Custom Error: $errorMessage',
style: const TextStyle(color: Colors.red),
),
),
defaultEmptyBuilder: (context, emptyMessage) => const Center(
child: Text('No Data Available'),
),
);
```
### State-Specific Callbacks
Handle different states with custom callbacks:
```dart
LoadingStateHandlerWidget(
loading: isLoading,
error: hasError,
empty: isEmpty,
onLoading: (defaultCallback, context, message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Custom Loading...'),
),
);
},
onError: (defaultCallback, context, message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Custom Error...'),
),
);
},
onEmpty: (defaultCallback, context, message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message ?? 'Custom Empty...'),
),
);
},
child: ContentWidget(),
);
```
### Disable State Changes
Control widget behavior granularly:
```dart
LoadingStateHandlerWidget(
disableWidgetChanges: false,
disableErrorWidgetChanges: true,
disableEmptyWidgetChanges: false,
// ... other properties
);
```
### State Change Callback
Track state transitions with the `onStateChange` callback:
```dart
LoadingStateHandlerWidget(
currentState: currentState,
onStateChange: (oldState, newState) {
print('State changed from $oldState to $newState');
// You can use this to log state transitions or trigger additional actions
},
child: YourContentWidget(),
);
```
### Custom Child Builder
Customize the child widget based on the current state:
```dart
LoadingStateHandlerWidget(
currentState: currentState,
childBuilder: (context, currentState, child) {
// Add a colored border based on the current state
return Container(
decoration: BoxDecoration(
border: Border.all(
color: _getStateColor(currentState),
width: 2.0,
),
borderRadius: BorderRadius.circular(8.0),
),
padding: const EdgeInsets.all(16.0),
child: child, // The original child widget
);
},
child: YourContentWidget(),
);
// Helper method to get color based on state
Color _getStateColor(CurrentStateEnum state) {
switch (state) {
case CurrentStateEnum.normal: return Colors.grey;
case CurrentStateEnum.loading: return Colors.blue;
case CurrentStateEnum.data: return Colors.green;
case CurrentStateEnum.empty: return Colors.amber;
case CurrentStateEnum.error: return Colors.red;
default: return Colors.grey;
}
}
```
## Properties
| Property | Type | Description |
| --------------------------- | -------------------------------- | ---------------------------------------------------------- |
| `controller` | `LoadingStateHandlerController?` | Controller instance used to manage the state of the widget |
| `currentState` | `CurrentStateEnum` | Current state of the widget |
| `onStateChange` | `OnStateChange?` | Callback when state changes, provides old and new states |
| `childBuilder` | `ChildBuilder?` | Builder for customizing the child widget based on state |
| `errorTitle` | `String?` | Custom error title |
| `retryButtonStyle` | `ButtonStyle?` | Custom retry button style |
| `retryButtonTextStyle` | `TextStyle?` | Custom retry button text style |
| `retryMessageStyle` | `TextStyle?` | Custom retry message style |
| `retryButtonText` | `String?` | Custom retry button text |
| `retryMessage` | `String?` | Custom retry message |
| `loadingWidget` | `Widget?` | Custom loading widget |
| `errorWidget` | `Widget?` | Custom error widget |
| `emptyWidget` | `Widget?` | Custom empty widget |
| `disableWidgetChanges` | `bool` | Disables state changes in the widget |
| `disableErrorWidgetChanges` | `bool` | Disables state changes in the error widget |
| `disableEmptyWidgetChanges` | `bool` | Disables state changes in the empty widget |
| `enableRetry` | `bool` | Enables retry functionality |
| `retryCooldown` | `Duration` | Cooldown period between retries |
| `onRetry` | `VoidCallback` | Callback when retry is triggered |
| `errorMessage` | `String?` | Custom error message |
| `loadingMessage` | `String?` | Custom loading message |
| `emptyMessage` | `String?` | Custom empty state message |
## Example
Check out the [example](example/lib/main.dart), [retry example](example/lib/retry_example.dart), and [controller example](example/lib/loading_state_handler_with_controller_example.dart) for a complete demonstration of all features.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.