How to await for network connectivity status in Flutter

708 views Asked by At

I have used connectivity_plus and internet_connection_checker packages to check the Internet connectivity.

The problem that occurred was the app worked perfectly fine as expected when the app started with Internet on state. But when the app is opened with the Internet connection off, the dialog isn't shown!!

I assume this is happening because the build method is called before the stream of Internet is listened to.

Code:

class _HomePageState extends State<HomePage> {
  late StreamSubscription subscription;
  bool isDeviceConnected = false;
  bool isAlertSet = false;

  @override
  void initState() {
    getConnectivity();
    super.initState();
  }

  getConnectivity() {
    subscription = Connectivity().onConnectivityChanged.listen(
      (ConnectivityResult result) async {
        isDeviceConnected = await InternetConnectionChecker().hasConnection;
        if (!isDeviceConnected && isAlertSet == false) {
          showDialogBox();
          setState(() {
            isAlertSet = true;
          });
        }
      },
    );
  }

  @override
  void dispose() {
    subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...
    );
  }

  showDialogBox() => showDialog(/* no internet dialog */)

Extending the question: Is it assured that this works for all the pages?

  • if yes, how?
  • if not, how can I overcome this?
2

There are 2 answers

2
Ahmad hassan On
  1. First of all you need to listen for internet connectivity in your app first screen which is probably app.dart

     GlobalKey<NavigatorState> navigatorKey = GlobalKey();
    
     final noInternet = NoInternetDialog();
    
     class TestApp extends StatefulWidget {
      @override
      State<TestApp> createState() => _TestAppState();
      }
    
     class _TestAppState extends State<TestApp> {
      @override
      void initState() {
        super.initState();
        checkInternetConnectivity();
       }
    
     @override
     Widget build(BuildContext context) {
      return MaterialApp(...);
     }
    
    Future<void> checkInternetConnectivity() async {
      Connectivity().onConnectivityChanged.getInternetStatus().listen((event) 
       {
       if (event == InternetConnectionStatus.disconnected) {
         if (!noInternet.isShowing) {
           noInternet.showNoInternet();
         }
       }
       });
      }
     }
    
  2. Make the screen stateful in which you are calling MaterialApp and in initState of that class check for your internet connection, like above

  3. You are saying how can I show dialog when internet connection changes for that you have to create a Generic class or extension which you can on connectivity change. You have to pass context to that dialogue using NavigatorKey

    class NoInternetDialog {
     bool _isShowing = false;
     NoInternetDialog();
    
     void dismiss() {
      navigatorKey.currentState?.pop();
      }
    
      bool get isShowing => _isShowing;
    
      set setIsShowing(bool value) {
     _isShowing = value;
     }
    
     Future showNoInternet() {
      return showDialog(
       context: navigatorKey.currentState!.overlay!.context,
       barrierDismissible: true,
       barrierColor: Colors.white.withOpacity(0),
       builder: (ctx) {
         setIsShowing = true;
         return AlertDialog(
           elevation: 0,
           backgroundColor: Colors.transparent,
           insetPadding: EdgeInsets.all(3.0.h),
           content: Container(...),
         );
       },
      );
     }
    }
    
1
user18309290 On

Use checkConnectivity to check current status. Only changes are exposed to the stream.

final connectivityResult = await Connectivity().checkConnectivity();