How to show different Widget when user is offline while using StreamBuilder?
You can add Error to Stream
and catch it in StreamBuilder
like this:
_someStreamCtrl.addError(error); // Client is offline
And in StreamBuilder
:
StreamBuilder<String>(
stream: someStream,
initialData: [],
builder: (BuildContext context,
AsyncSnapshot<String> snap) {
if (snap.hasError)
return ErrorWidget(); //Error
if (snap.hasData)
return // Desired widget
//if waiting
return CircularProgressIndicator();
);
},
);
Pritish
Updated on December 08, 2022Comments
-
Pritish over 1 year
I am trying to fetch some data from the internet. With the use of
FutureBuilder
, handling for various cases like offline, online,error is quite easy but I am usingStreamBuilder
and I am not able to understand how to handle offline caseFollowing is my code to use StreamBuilder which works but I have not handled offline data or error
return StreamBuilder( builder: (context, AsyncSnapshot<SchoolListModel> snapshot) { if (snapshot.hasError) { return Expanded( child: Center( child: Text(SOMETHING_WENT_WRONG), )); } if (!snapshot.hasData) { return Expanded( child: Center( child: CircularProgressIndicator(), ), ); } if (snapshot.data != null) { if (snapshot.data.status == 1) { return buildSchoolList(snapshot.data.schoolListData); } else { showMessageDialog(snapshot.data.msg.toString(), context); } } }, stream: schoolListBloc.schoolList, ); }
Now to handle the offline case I am doing the following two options which don't work in my case
Option one.
return StreamBuilder( builder: (context, AsyncSnapshot<SchoolListModel> snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return Text(SOMETHING_WENT_WRONG); case ConnectionState.active: case ConnectionState.waiting: return Expanded( child: Center( child: CircularProgressIndicator(), ), ); case ConnectionState.done: if (snapshot.hasError) { return errorData(snapshot); } else { if (snapshot.data.status == 1) { return buildSchoolList(snapshot.data.schoolListData); } else { showMessageDialog(snapshot.data.msg.toString(), context); } } } }, stream: schoolListBloc.schoolList, ); }
I keep seeing the
CircularProgressIndicator
and no error on the console. I fail to understand why the above switch case works forFuturBuilder
and notStreamBuilder
.Second Option.
Future<bool> checkInternetConnection() async { try { final result = await InternetAddress.lookup('google.com'); if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { print('connected'); return true; } } on SocketException catch (_) { print('not connected'); return false; } return false; } return StreamBuilder( builder: (context, AsyncSnapshot<SchoolListModel> snapshot) { checkInternetConnection().then((isAvailable) { if (isAvailable) { if (!snapshot.hasData || snapshot.data == null) { return Center( child: CircularProgressIndicator(), ); } if (snapshot.data != null) { if (snapshot.data.status == 1) { return buildSchoolList(snapshot.data.schoolListData); } else { showMessageDialog(snapshot.data.msg.toString(), context); } } } else { return Center( child: Column( children: <Widget>[ Text(CHECK_YOUR_INTERNET_CONNECTION), RaisedButton( onPressed: () {}, child: Text(TRY_AGAIN), ) ], ), ); } }); }, stream: schoolListBloc.schoolList, ); }
Using this option throws the following error
the following assertion was thrown building StreamBuilder<SchoolListModel>(dirty, state: I/flutter ( 5448): _StreamBuilderBaseState<SchoolListModel, AsyncSnapshot<SchoolListModel>>#dd970): I/flutter ( 5448): A build function returned null. I/flutter ( 5448): The offending widget is: StreamBuilder<SchoolListModel> I/flutter ( 5448): Build functions must never return null. To return an empty space that causes the building widget to I/flutter ( 5448): fill available room, return "new Container()". To return an empty space that takes as little room as..
What approach should I take with the following cases of offline, online and error data when using StreamBuilder