Flutter: StreamProvider catchError how to
Asked Answered
J

4

7

I was wondering if someone could show me how to implement the Flutter StreamProvider "catchError" property?

Example code below to add to:

StreamProvider<LocationModelNormal>.value(
    initialData: LocationModelNormal.initialData(),
    stream: locationStreamInstance.specificLocation(_secondWonder),
    catchError: ?????????
),
class LocationModelNormal {
  final String name;
  LocationModelNormal({
    this.name
  });
  factory LocationModelNormal.fromMap(Map<String, dynamic> data) {
    return LocationModelNormal(
      name: data['name'] ?? '',

    );
  }
  factory LocationModelNormal.initialData() {
    return LocationModelNormal(
      name: '',
    );
  }
}
Jugoslavia answered 8/7, 2019 at 21:44 Comment(0)
P
18

You'll want to model your data using sealed classes:

abstract class Data {}

class Content implements Data {
  Content(this.data);

  final List<String> data;
}

class Error implements Data {
  Error(this.msg);

  final String msg;
}

class Loading implements Data {
  const Loading();
}

Then used like so in the provider:

StreamProvider<Data>(
  builder: (_) async* {
    yield Content(['hello', 'world']);
  },
  initialData: const Loading(),
  catchError: (_, err) => Error(err.toString()),
  child: Container(),
);

And consumed as such:

Consumer<Data>(
  builder: (_, data, __) {
    if (data is Loading) {
      return const CircularProgressIndicator();
    } else if (data is Error) {
      return Center(child: Text(data.msg));
    } else if (data is Content) {
      return ListView.builder(
        itemCount: data.data.length,
        itemBuilder: (_, index) => Text(data.data[index]),
      );
    }
    throw FallThroughError();
  },
);
Pray answered 9/7, 2019 at 21:27 Comment(0)
U
0

Easy fix for now.

@override
Widget build(BuildContext context) {
 return StreamProvider<UserModel?>.value(
  value: AuthenticationService().user,
  initialData: null,
  catchError: (_, err) => null,
  child: const MaterialApp(
    home: AuthWrapper(),
  ),
);
}
}
Upshaw answered 6/3, 2022 at 18:0 Comment(0)
D
0

Remi of course has the most thorough and proper method, since in the case of an error, you need to provide a value in its place or make it nullable. His solution is the most complete.

However, if you have other things already established, and need a down and dirty solution: Below I make it nullable with the ? and return a null value in the case of an error. The return is not technically necessary.

StreamProvider<LocationModelNormal?>.value(
    initialData: LocationModelNormal.initialData(),  //or null maybe better
    stream: locationStreamInstance.specificLocation(_secondWonder),
    catchError: (context, e) {
              print('error in LocationModelNormal: ${e.toString()}');
              //or pop a dialogue...whatever.
              return null;
            },
),
Doublethink answered 7/6, 2022 at 22:47 Comment(0)
G
-1

You can also do this

StreamProvider<DocumentSnapshot>.value(
        value: api.myDetails(mail),
        child: Builder(
          builder: (context){
            var snapshot = Provider.of<DocumentSnapshot>(context);
            if(snapshot == null){
              return customF.loadingWidget();
            }else{
              return Stack(
                children: <Widget>[
                  getMainListViewUI(),
                  getAppBarUI(),
                  SizedBox(
                    height: MediaQuery.of(context).padding.bottom,
                  )
                ],
              );
            }
          }
        ),
      ),
Gagnon answered 18/12, 2019 at 21:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.