Reputation: 477
I have a stream in my flutter app that is continuosly detecting the network change .It is defined in the main function.
Map _source = {ConnectivityResult.none: false};
CurrentConnectivity _connectivity = CurrentConnectivity.instance;
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await init();
HttpOverrides.global = new MyHttpOverrides();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
_source=source;
}, onError: (err) {
print(err);
}, cancelOnError: false);
runApp(AppWidget());
_connectivity.disposeStream();
}
But when i navigate i get this exception
EXCEPTION
E/flutter ( 6822): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Bad state: Cannot add new events after calling close
E/flutter ( 6822): #0 _BroadcastStreamController.add (dart:async/broadcast_stream_controller.dart:251:24)
E/flutter ( 6822): #1 _StreamSinkWrapper.add (dart:async/stream_controller.dart:873:13)
E/flutter ( 6822): #2 CurrentConnectivity._checkStatus (package:iris_flutter/core/network/current_connectivity.dart:61:21)
E/flutter ( 6822): #3 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #4 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter ( 6822): #5 _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter ( 6822): #6 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter ( 6822): #7 Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter ( 6822): #8 Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter ( 6822): #9 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
E/flutter ( 6822): #10 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
E/flutter ( 6822): #11 SendOfflineRequests.call (package:iris_flutter/features/faculty/attendance/domain/usecases/offline_requests/send_offline_requests.dart)
E/flutter ( 6822): #12 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #13 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter ( 6822): #14 _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter ( 6822): #15 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter ( 6822): #16 Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter ( 6822): #17 Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter ( 6822): #18 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
E/flutter ( 6822): #19 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
E/flutter ( 6822): #20 OfflineClassesRepositoryImpl.sendOfflineRequests (package:iris_flutter/features/faculty/attendance/data/repositories/offline_requests_repository_impl.dart)
E/flutter ( 6822): #21 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #22 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter ( 6822): #23 _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter ( 6822): #24 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter ( 6822): #25 Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter ( 6822): #26 Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter ( 6822): #27 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
E/flutter ( 6822): #28 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
E/flutter ( 6822): #29 StudentDetailsFacultyLocalDataSourceImpl.deleteAllMarkedRecords (package:iris_flutter/features/faculty/attendance/data/datasources/students/student_details_faculty_local_data_source.dart)
E/flutter ( 6822): #30 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #31 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter ( 6822): #32 _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter ( 6822): #33 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter ( 6822): #34 Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter ( 6822): #35 Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter ( 6822): #36 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
E/flutter ( 6822): #37 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
E/flutter ( 6822): #38 LocalStorage.deleteAllStoredMarkings (package:iris_flutter/core/util/local_storage.dart)
E/flutter ( 6822): #39 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #40 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter ( 6822): #41 _FutureListener.handleValue (dart:async/future_impl.dart:141:18)
E/flutter ( 6822): #42 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:682:45)
E/flutter ( 6822): #43 Future._propagateToListeners (dart:async/future_impl.dart:711:32)
E/flutter ( 6822): #44 Future._completeWithValue (dart:async/future_impl.dart:526:5)
E/flutter ( 6822): #45 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:36:15)
E/flutter ( 6822): #46 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:298:13)
E/flutter ( 6822): #47 DeleteStatement.go.<anonymous closure> (package:moor/src/runtime/query_builder/statements/delete.dart)
E/flutter ( 6822): #48 _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter ( 6822): #49 _
I/Toast ( 6822): Show toast from OpPackageName:com.example.iris_flutter, PackageName:com.example.iris_flutter
It works if i do not dispose the stream but i have heard that it is not a good practice to leave the stream open. Is there a better way to close the stream or is closing the stream necessary.
EDIT1 For some answers that say that i need to use WidgetsBindingObserver i want to point out that i need to initialise the stream in main ,else the connectivity change is detected multiple times if i initialise it in a stateful/stateless widget, which breaks some logic in the code i have written.
class LifeCycle extends StatefulWidget {
@override
_LifeCycleState createState() => _LifeCycleState();
}
class _LifeCycleState extends State<LifeCycle> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print(state);
if(state==AppLifecycleState.paused){
GlobalClassThatInitialisesStream.disposeConnectivityStream();
}
if(state==AppLifecycleState.resumed){
GlobalClassThatInitialisesStream.initialiseConnectivityStream();
}
}
@override
Widget build(BuildContext context) {
return AppWidget();
}
}
Upvotes: 2
Views: 15539
Reputation: 8978
See if you are really looking for a disposing your stream in flutter. The best way to do it using via Flutter dispose.
To give you a jist about what inbuilt
dispose()
method does is, when yourState
is not active or finishes, it destroys yourChangeNotifiers/Controllers/Streams etc
, and prevents your State to rebuild again, hence you don't see that error/warning
So, just make sure you have that in your StatefulWidget()
@override
void dispose() {
// you dispose your stream here
// or check if that works out _connectivity.dispose();
_connectivity.disposeStream();
super.dispose();
}
Hope that helps :)
Upvotes: 1
Reputation: 648
I dont really get the exact question your trying to ask.
A. IF you want to close the stream on app exit You can just call stream.cancel() when the app exits. How to detect when the app exits? For that you can make use of life cycle in flutter. Check the following youtube tutorial to learn more about it.
B.IF you are trying to fix the exception that is being raised due to navigation Create a separate global class that checks for network connectivity. And initialize the stream inside rather than in the main function. This way when you navigate out of the main you will not see this exception.
Upvotes: 3