declarative_async_widget 0.2.0 copy "declarative_async_widget: ^0.2.0" to clipboard
declarative_async_widget: ^0.2.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 FutureBuilder and StreamBuilder, which are designed to reduce boilerplate and improve error handling. More specifically, 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 #

All constructors and an example of their usage are shown below. Every snippet includes only the required parameters.

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 parameters #

  • bool disposeOnFutureChange

    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.

    Default value: true.

  • bool printErrorsToConsole

    Whether or not to print errors to the console.

    Default value:

    • false with the default and noLoading constructors
    • true with the noError and onlyValue constructors (can't be set to false in these cases: in case of unexpected errors they will be printed)
  • void Function(FlutterErrorDetails details) reportError

    If provided, overrides the function that prints errors to the console.

    Default value: null.

  • bool keepAlive

    Whether or not we should send a keep alive notification with AutomaticKeepAliveClientMixin.

    Default value: false.

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