Home > Software design >  How to yield an Exception in a stream so that it can be caught in widget tree?
How to yield an Exception in a stream so that it can be caught in widget tree?

Time:11-11

I can't seem to find a way to intentionally yield or throw an error in a stream in such a way that can be used by an AsyncValue widget in the tree (using Riverpod for State Management).

class AsyncValueWidget<T> extends StatelessWidget {
   AsyncValueWidget(
      {Key? key,
      required this.value,
      required this.data
      : super(key: key);
  final AsyncValue<T> value;
  final Widget Function(T) data;

  @override
  Widget build(BuildContext context) {
    return value.when(
      data: data
      error: (e, st) => Center(child: ErrorMessageWidget(e.toString())),
      loading: () => const Center(child: CircularProgressIndicator()),
    );
  }
}

I want the stream in my fake repo to return a value in certain cases and Exception in other cases: `

  Stream<T> function() async* {
    await Future.delayed(const Duration(milliseconds: 500));

    switch (condition) {
      case condition 1:
        yield value1;
        break;
      case condition 2:
        yield value2;
        break;
      case condition 3:
        // neither these work
        throw Exception('You should not be able to call this function under this condition');
        yield* Stream.error()...
      case condition 4:
        yield null;
        break;
    }
  }

`

Unfortunately, the Exception/Error does not seem to make it to the widget and I get a nasty red screen. I've also tried try/catch to no avail. Any ideas?

CodePudding user response:

if you are working with a service, I recommend FutureBuilder. for more info you can check here https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

FutureBuilder(
              future: controller.mainFuture.value,
              builder: (context, snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.active:
                  case ConnectionState.waiting:
                    return Container(
                      color: Colors.white,
                      width: context.width,
                      height: context.height,
                      child: globalShimmer(height: 50, itemCount: 10),
                    );
                  case ConnectionState.done:
                    if (snapshot.hasError) {
                      return Container();
                    }
                    return Container();
                  default:
                    return Container();
                }
              });

CodePudding user response:

To return a fake error to a stream using riverpod, just simply return Stream.error('Something went wrong'):

final fakeErrorStreamProvider = StreamProvider.autoDispose<List<T>>(
  (ref) {
    return Stream.error('something went wrong');
  },
);

or

  Stream<List<T>> watchWhatever() => Stream.error('Something went wrong.');

Your AsyncValueWidget will catch this error from the UI.

  • Related