builder_plus 1.1.5 copy "builder_plus: ^1.1.5" to clipboard
builder_plus: ^1.1.5 copied to clipboard

A Flutter package for simplified async operations with built-in loading, error, and empty states management.

Repository on GitHub | Report an Issue

builder_plus Package #

A Flutter package to simplify the management of asynchronous operations with loading, error, and empty data states.

Features #

  • FutureWorker: Simplified wrapper for FutureBuilder
  • StreamWorker: Simplified wrapper for StreamBuilder
  • State Widgets: OptionLoading, OptionEmpty, OptionError
  • Error Handling: Automatic error management with retry option
  • Production Mode: Hides empty states in production

Installation #

dependencies:
  builder_plus: <latest_version>

Example #

Here is a complete example using all main features of the package:

import 'package:flutter/material.dart';
import 'package:builder_plus/builder_plus.dart';
import 'package:builder_plus/model/option_loading.dart';
import 'package:builder_plus/model/option_empty.dart';
import 'package:builder_plus/model/option_error.dart';

// A custom class to illustrate typing
typedef Id = int;

class Example {
  final Id id;
  final String name;

  Example(this.id, this.name);

  @override
  String toString() => 'Example(id: $id, name: $name)';
}

// Simulate an asynchronous operation on an Example
Future<Example?> processExample(Example example, {bool throwError = false, bool empty = false}) async {
  await Future.delayed(const Duration(seconds: 2));
  if (throwError) throw Exception('Network error');
  if (empty) return null;
  return Example(example.id, example.name.toUpperCase());
}

// Simulate a stream of operations on an Example
Stream<Example?> streamExample(Example example, {bool throwError = false, bool empty = false}) async* {
  yield null;
  await Future.delayed(const Duration(seconds: 1));
  if (throwError) throw Exception('Stream error');
  if (empty) yield null;
  else yield Example(example.id, example.name.toUpperCase());
  await Future.delayed(const Duration(seconds: 1));
  yield Example(example.id, ' [1m${example.name.toUpperCase()} (final)');
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'builder_plus Example',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const ExampleScreen(),
    );
  }
}

class ExampleScreen extends StatefulWidget {
  const ExampleScreen({super.key});

  @override
  State<ExampleScreen> createState() => _ExampleScreenState();
}

class _ExampleScreenState extends State<ExampleScreen> {
  bool throwFutureError = false;
  bool throwStreamError = false;
  bool showEmpty = false;

  @override
  Widget build(BuildContext context) {
    final example = Example(1, 'demo');
    return Scaffold(
      appBar: AppBar(title: const Text('FutureWorker & StreamWorker Example')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Checkbox(
                  value: throwFutureError,
                  onChanged: (v) => setState(() => throwFutureError = v ?? false),
                ),
                const Text('Future Error'),
                const SizedBox(width: 16),
                Checkbox(
                  value: throwStreamError,
                  onChanged: (v) => setState(() => throwStreamError = v ?? false),
                ),
                const Text('Stream Error'),
                const SizedBox(width: 16),
                Checkbox(
                  value: showEmpty,
                  onChanged: (v) => setState(() => showEmpty = v ?? false),
                ),
                const Text('Empty State'),
              ],
            ),
            const SizedBox(height: 24),
            const Text('FutureWorker', style: TextStyle(fontWeight: FontWeight.bold)),
            FutureWorker<Example?>(
              future: processExample(example, throwError: throwFutureError, empty: showEmpty),
              builder: (context, result) => Text(
                'After processing: \n [1m [0m${result.toString()}',
                style: const TextStyle(fontSize: 18),
              ),
              loadingBuilder: (context) => const OptionLoading(size: 32),
              emptyBuilder: (context) => const OptionEmpty(
                text: 'No data received',
                icon: Icons.hourglass_empty,
              ),
              errorBuilder: (context, error) => OptionError(
                error: error.toString(),
                onRetry: () => setState(() {}),
                retryButtonText: 'Retry',
              ),
            ),
            const SizedBox(height: 32),
            const Text('StreamWorker', style: TextStyle(fontWeight: FontWeight.bold)),
            StreamWorker<Example?>(
              stream: streamExample(example, throwError: throwStreamError, empty: showEmpty),
              builder: (context, result) => Text(
                'Stream: \n${result.toString()}',
                style: const TextStyle(fontSize: 18),
              ),
              loadingBuilder: (context) => const OptionLoading(size: 32, color: Colors.orange),
              emptyBuilder: (context) => const OptionEmpty(
                text: 'Empty stream',
                icon: Icons.stream,
                iconColor: Colors.orange,
              ),
              errorBuilder: (context, error) => OptionError(
                error: error.toString(),
                onRetry: () => setState(() {}),
                retryButtonText: 'Restart stream',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Parameters #

FutureWorker / StreamWorker #

Parameter Type Description
`future stream` `Future
builder Widget Function(BuildContext, T) Builder for the data
isProd bool Production mode (hides empty states)
initialData T? Initial data
emptyBuilder Widget Function(BuildContext)? Builder for empty state
errorBuilder Widget Function(BuildContext, Object?)? Builder for error
loadingBuilder Widget Function(BuildContext)? Builder for loading

OptionLoading #

Parameter Type Default Description
size double 24.0 Indicator size
color Color? null Color (uses theme if null)

OptionEmpty #

Parameter Type Default Description
text String - Text to display
icon IconData? null Optional icon
textStyle TextStyle? null Text style
iconSize double 48.0 Icon size
iconColor Color? null Icon color
spacing double 16.0 Spacing

OptionError #

Parameter Type Default Description
error String - Error message
onRetry VoidCallback? null Retry callback
textStyle TextStyle? null Text style
iconSize double 48.0 Icon size
iconColor Color? null Icon color
spacing double 16.0 Spacing
showRetryButton bool true Show retry button
retryButtonText String 'Retry' Retry button text
1
likes
0
points
131
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package for simplified async operations with built-in loading, error, and empty states management.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on builder_plus