'Simple Bloc Pattern and Network Connection check
Thank you for checking out my question :). I appreciate it!
What I am trying to do
I am trying to check if the user has an internet connection or not. For this, I use the bloc pattern. I am just starting out and I don't know what to do with these errors.
What the error messages are
The relevant error-causing widget was: TestScreen Testscreen:file//filepath (etc,etc)
Another exception was thrown: Each child must be laid out exactly once. Another exception was thrown: Updated layout information required for RenderErrorBox NEEDS-LAYOUT NEEDS-PAINT to calculate semantics.
Another exception was thrown: Bad state: Future already completed.
I am new and these errors are overwhelming. These errors tell me nothing. I hope you can help me out!
Code
Homescreen
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
static String routeName = '/home';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Homepage'),
),
body: BlocProvider(
create: (context) => NetworkBloc()..add(ListenConnection()),
child: TestScreen(),
));
}
}
class TestScreen extends StatelessWidget {
const TestScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: BlocBuilder<NetworkBloc, NetworkState>(
builder: (context, state) {
if (state is ConnectionFailure) return Text("No Internet Connection");
if (state is ConnectionSuccess)
return Text("You're Connected to Internet");
else
return Text("");
},
),
);
}
}
Network Block
class NetworkBloc extends Bloc<NetworkEvent, NetworkState> {
NetworkBloc() : super(ConnectionInitial());
late StreamSubscription _subscription;
@override
Stream<NetworkState> mapEventToState(NetworkEvent event) async* {
if (event is ListenConnection) {
_subscription = DataConnectionChecker().onStatusChange.listen((status) {
add(ConnectionChanged(status == DataConnectionStatus.disconnected
? ConnectionFailure()
: ConnectionSuccess()));
});
}
if (event is ConnectionChanged) yield event.connection;
}
@override
Future<void> close() {
_subscription.cancel();
return super.close();
}
}
Network Event
abstract class NetworkEvent {}
class ListenConnection extends NetworkEvent {}
class ConnectionChanged extends NetworkEvent {
NetworkState connection;
ConnectionChanged(this.connection);
}
Network State
abstract class NetworkState {}
class ConnectionInitial extends NetworkState {}
class ConnectionSuccess extends NetworkState {}
class ConnectionFailure extends NetworkState {}
I hope you can help me out. Thank you very much!
Solution 1:[1]
There are a lot of issues with your code so I'm not sure if I got all of them.
- You should not call
.add()if you don't have registered event handler
//This is how you should register an event handler
NetworkBloc() : super(ConnectionInitial()) {
on<ListenConnection>((event, emit) {
// TODO: implement event handler
});
}
- You are overriding a function
mapEventToState(), when it doesn't override any of inherited methods
//@override NO NEED OF OVERRIDE HERE
Stream<NetworkState> mapEventToState(NetworkEvent event) async* {
if (event is ListenConnection) {
_subscription = DataConnectionChecker().onStatusChange.listen((status) {
add(ConnectionChanged(status == DataConnectionStatus.disconnected
? ConnectionFailure()
: ConnectionSuccess()));
});
}
if (event is ConnectionChanged) yield event.connection;
}
And I'm not sure if this is intended, but your mapEventToState() also never gets called and without any emit() methods your UI will never rebuild.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
