Un package Flutter pour simplifier la gestion des opérations asynchrones avec des états de chargement, d'erreur et de données vides.
- FutureWorker : Wrapper simplifié pour FutureBuilder
- StreamWorker : Wrapper simplifié pour StreamBuilder
- Widgets d'état : OptionLoading, OptionEmpty, OptionError
- Gestion d'erreurs : Gestion automatique des erreurs avec possibilité de retry
- Mode production : Masquage des états vides en production
dependencies:
builder_plus: 1.0.1
import 'package:data_builder/data_builder.dart';
FutureWorker<User>(
future: userService.getUser(id),
builder: (context, user) => UserCard(user: user),
errorBuilder: (context, error) => ErrorWidget(error.toString()),
loadingBuilder: (context) => CircularProgressIndicator(),
)
import 'package:workers/workers_helper.dart';
StreamWorker<User>(
stream: userService.userStream,
builder: (context, user) => UserCard(user: user),
errorBuilder: (context, error) => ErrorWidget(error.toString()),
loadingBuilder: (context) => CircularProgressIndicator(),
)
// Loading avec personnalisation
const OptionLoading(
size: 32.0,
color: Colors.blue,
)
// Empty avec icône
const OptionEmpty(
text: 'Aucun utilisateur trouvé',
icon: Icons.person_off,
iconSize: 64.0,
)
// Error avec retry
OptionError(
error: 'Erreur de connexion',
onRetry: () => userService.refresh(),
retryButtonText: 'Actualiser',
)
| Paramètre |
Type |
Description |
future | steam |
Future | stream |
Future<T> | Stream<T>, La source de données |
builder |
Widget Function(BuildContext, T) |
Builder pour les données |
isProd |
bool |
Mode production (masque les états vides) |
initialData |
T? |
Données initiales |
emptyBuilder |
Widget Function(BuildContext)? |
Builder pour état vide |
errorBuilder |
Widget Function(BuildContext, Object?)? |
Builder pour erreur |
loadingBuilder |
Widget Function(BuildContext)? |
Builder pour chargement |
| Paramètre |
Type |
Défaut |
Description |
size |
double |
24.0 |
Taille de l'indicateur |
color |
Color? |
null |
Couleur (utilise le thème si null) |
| Paramètre |
Type |
Défaut |
Description |
text |
String |
- |
Texte à afficher |
icon |
IconData? |
null |
Icône optionnelle |
textStyle |
TextStyle? |
null |
Style du texte |
iconSize |
double |
48.0 |
Taille de l'icône |
iconColor |
Color? |
null |
Couleur de l'icône |
spacing |
double |
16.0 |
Espacement |
| Paramètre |
Type |
Défaut |
Description |
error |
String |
- |
Message d'erreur |
onRetry |
VoidCallback? |
null |
Callback de retry |
textStyle |
TextStyle? |
null |
Style du texte |
iconSize |
double |
48.0 |
Taille de l'icône |
iconColor |
Color? |
null |
Couleur de l'icône |
spacing |
double |
16.0 |
Espacement |
showRetryButton |
bool |
true |
Afficher le bouton retry |
retryButtonText |
String |
'Réessayer' |
Texte du bouton |
class UserListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Utilisateurs')),
body: FutureWorker<List<User>>(
future: userService.getUsers(),
builder: (context, users) {
if (users.isEmpty) {
return const OptionEmpty(
text: 'Aucun utilisateur trouvé',
icon: Icons.people_outline,
);
}
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) => UserListItem(user: users[index]),
);
},
errorBuilder: (context, error) => OptionError(
error: 'Impossible de charger les utilisateurs',
onRetry: () => setState(() {}),
),
loadingBuilder: (context) => const OptionLoading(size: 32.0),
),
);
}
}
class ChatScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Chat')),
body: StreamWorker<List<Message>>(
stream: chatService.messagesStream,
builder: (context, messages) {
return ListView.builder(
itemCount: messages.length,
itemBuilder: (context, index) => MessageItem(message: messages[index]),
);
},
errorBuilder: (context, error) => OptionError(
error: 'Erreur de connexion au chat',
onRetry: () => chatService.reconnect(),
),
),
);
}
}
Les contributions sont les bienvenues ! N'hésitez pas à ouvrir une issue ou une pull request.