declarative_async_widget 0.1.0 copy "declarative_async_widget: ^0.1.0" to clipboard
declarative_async_widget: ^0.1.0 copied to clipboard

discontinued

FutureWidget and StreamWidget - Declarative FutureBuilder and StreamBuilder

FutureWidget and StreamWidget - Improved FutureBuilder and StreamBuilder. #

This package provides FutureWidget and StreamWidget, two widgets similar to StreamBuilder and FutureBuilder, which are designed to reduce boilerplate and improve error handling.

It is a rewrite of the package async_builder.

How it differs from async_builder

In async_builder, multiple mutually exclusive events can coexist (e.g. giving both a stream and a future (which throws a runtime error), assigning both a waiting and an initialData, defining stream-only relevant params with a Future, ...); declarative_async_widget aims to address this and, at the same time, bring more clarity.

How to use #

1. Add to dependencies

dependencies:
  declarative_async_widget: ^latest # replace latest with version number

2. Import

import 'package:declarative_async_widget/declarative_async_widget.dart';

FutureWidget #

The future can't be null.

Constructors #

Default constructor

whenData, whenError and whenLoading are required. initialData can't be assigned since whenLoading is going to be used instead.

class ExampleWidget extends StatefulWidget {
  const ExampleWidget({Key? key}) : super(key: key);

  @override
  ExampleWidgetState createState() => ExampleWidgetState();
}

class ExampleWidgetState extends State<ExampleWidget> {
  final Future<int> _getInt = myFuture(false);

  static Future<int> myFuture(bool shouldThrow) async {
    await Future.delayed(const Duration(seconds: 4));
    if (shouldThrow) {
      throw Exception("You can't pass true as a param");
    }
    return 4;
  }

  @override
  Widget build(BuildContext context) {
    return FutureWidget<int>(
      future: _getInt,
      whenData: (context, data) => Text('My data is: $data'),
      whenError: (context, error, stackTrace) => Text('Error was thrown: $error'),
      whenLoading: (context) => const Text('Loading...'),
    );
  }
}

noError constructor

There is no whenError param. Make 100% sure the future can't throw an error, else an AsyncWidgetUnexpectedError will be thrown at runtime.

class ExampleWidgetState extends State<ExampleWidget> {
  final Future<int> _getInt = myFuture();

  static Future<int> myFuture() async {
    await Future.delayed(const Duration(seconds: 4));
    return 4;
  }

  @override
  Widget build(BuildContext context) {
    return FutureWidget<int>.noError(
      future: _getInt,
      whenData: (context, data) => Text('My data is: $data'),
      whenLoading: (context) => const Text('Loading...'),
    );
  }
}

noLoading constructor

There is no whenLoading param, since in this case some initial data is present/given before the future has even fired; an initialData argument is therefore required.

class ExampleWidgetState extends State<ExampleWidget> {
  final Future<int> _getInt = myFuture(true);

  static Future<int> myFuture(bool shouldThrow) async {
    await Future.delayed(const Duration(seconds: 4));
    if (shouldThrow) {
      throw Exception("You can't pass true as a param");
    }
    return 4;
  }

  @override
  Widget build(BuildContext context) {
    return FutureWidget<int>.noLoading(
      future: _getInt,
      whenData: (context, data) => Text('My data is: $data'),
      initialData: 99999,
      whenError: (BuildContext context, Object error, StackTrace? stackTrace) =>
          Text('Error was thrown: $error'),
    );
  }
}

onlyData constructor

This constructor integrates noError and noLoading. Therefore:

  • no whenError param
  • no whenLoading param
  • initialData is required
class ExampleWidgetState extends State<ExampleWidget> {
  final Future<int> _getInt = myFuture();

  static Future<int> myFuture() async {
    await Future.delayed(const Duration(seconds: 4));
    return 4;
  }

  @override
  Widget build(BuildContext context) {
    return FutureWidget<int>.onlyData(
      future: _getInt,
      whenData: (context, data) => Text('My data is: $data'),
      initialData: 99999,
    );
  }
}

Additional Params #

/// Whether or not the state of this widget should be disposed (and therefore
/// the widget rebuilt) when the [future] instance changes.
///
/// If false, the current data should be retained.
final bool disposeOnFutureChange;

/// Whether or not to print errors to the console.
final bool printErrorsToConsole;

/// If provided, overrides the function that prints errors to the console.
final void Function(FlutterErrorDetails details) reportError;

/// Whether or not we should send a keep alive
/// notification with [AutomaticKeepAliveClientMixin].
final bool keepAlive;

StreamWidget #

It is similar to FutureWidget, but uses streams. Examples will be added in the future.

Issues with type inference #

Remember to specify the type, e.g., FutureWidget<int>.onlyData and not FutureWidget.onlyData, otherwise a dynamic or a nullable type might be inferred (e.g. the type returned by future is int, however FutureWidget's inferred type is int?, i.e., FutureWidget<int?>).

Note #

Complete documentation and tests will be added in the future.

1
likes
0
pub points
0%
popularity

Publisher

verified publishermanuelplavsic.ch

FutureWidget and StreamWidget - Declarative FutureBuilder and StreamBuilder

Repository (GitLab)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter, rxdart

More

Packages that depend on declarative_async_widget