如何在 Flutter 上持续检查互联网连接与否?

Posted

技术标签:

【中文标题】如何在 Flutter 上持续检查互联网连接与否?【英文标题】:How to continuously check internet connect or not on Flutter? 【发布时间】:2019-07-30 08:31:38 【问题描述】:

我使用此代码检查互联网。我也将此函数包装到 initState 中。当互联网不可用时,小吃栏始终显示。但是连接到互联网后,小吃店并没有消失。我不能使用连接插件,因为他们在 android 上说,该插件不能保证连接到 Internet。

 checking1(TextEditingController usernameController, BuildContext context,
      String _url, GlobalKey<ScaffoldState> _scaffoldKey) async 
    try 
      final result = await InternetAddress.lookup('google.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) 
        usernameController.text == '' ?
        showDialog(...some code...) :
        usernameValidation(usernameController.text, context, _url);
      
    
    on SocketException
    catch (_) 
      _showSnackBar(_scaffoldKey);
    
  

【问题讨论】:

【参考方案1】:

演示互联网连接及其来源的侦听器的完整示例。

Original post

import 'dart:async';
import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget 
  @override
  _HomePageState createState() => _HomePageState();


class _HomePageState extends State<HomePage> 
  Map _source = ConnectivityResult.none: false;
  MyConnectivity _connectivity = MyConnectivity.instance;

  @override
  void initState() 
    super.initState();
    _connectivity.initialise();
    _connectivity.myStream.listen((source) 
      setState(() => _source = source);
    );
  

  @override
  Widget build(BuildContext context) 
    String status = "Offline";
    switch (_source.keys.toList()[0]) 
      case ConnectivityResult.none:
        status = "Offline";
        break;
      case ConnectivityResult.mobile:
        status = "Mobile: Online";
        break;
      case ConnectivityResult.wifi:
        status = "WiFi: Online";
        break;
      case ConnectivityResult.ethernet:
        status = "Ethernet: Online";
        break;
    

    return Scaffold(
      appBar: AppBar(title: Text("Internet")),
      body: Center(child: Text(status)),
    );
  

  @override
  void dispose() 
    _connectivity.disposeStream();
    super.dispose();
  


class MyConnectivity 
  MyConnectivity._internal();

  static final MyConnectivity _instance = MyConnectivity._internal();

  static MyConnectivity get instance => _instance;

  Connectivity connectivity = Connectivity();

  StreamController controller = StreamController.broadcast();

  Stream get myStream => controller.stream;

  void initialise() async 
    ConnectivityResult result = await connectivity.checkConnectivity();
    _checkStatus(result);
    connectivity.onConnectivityChanged.listen((result) 
      _checkStatus(result);
    );
  

  void _checkStatus(ConnectivityResult result) async 
    bool isOnline = false;
    try 
      final result = await InternetAddress.lookup('example.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) 
        isOnline = true;
       else 
        isOnline = false;
      
     on SocketException catch (_) 
      isOnline = false;
    
    controller.sink.add(result: isOnline);
  

  void disposeStream() => controller.close();

【讨论】:

var 结果 = await Connectivity().checkConnectivity();给我类似“ConnectivityService:用户 11177 和当前进程都没有 android.permission.ACCESS_NETWORK_STATE.,null)”之类的错误有人可以帮忙吗? @JayMungara 我无法得到部分错误,您是否已将ACCESS_NETWORK_STATE 权限添加到您的AndroidManifest.xml 文件中? @JayMungara 如果您可以分享错误的屏幕截图会有所帮助。 在这里查看问题github.com/flutter/flutter/issues/40731 @JayMungara 你运行了我的代码,它工作了吗?您看到其中有任何错误吗?如果是,我很乐意在 *** 本身(不是 Github)上为您提供帮助,如果您可以提出问题并与我分享链接。【参考方案2】:

另一个选项也可以是这个包:https://pub.dartlang.org/packages/flutter_offline,它处理这个问题非常简单。

你需要先导入包'package:flutter_offline/flutter_offline.dart';

之后,您在 Widget 构建(BuildContext 上下文)中包含 OfflineBuilder,它将连续读取 ConnectivityResult 中的所有流更改。

喜欢链接上的例子或喜欢下面的例子

      @override
  Widget build(BuildContext context) 
    return OfflineBuilder(

        debounceDuration: Duration.zero,
        connectivityBuilder: (
            BuildContext context,
            ConnectivityResult connectivity,
            Widget child,
            ) 
          if (connectivity == ConnectivityResult.none) 

            return Scaffold(
              appBar: AppBar(
                title: const Text('Home'),
              ),
              body: Center(child: Text('Please check your internet connection!')),
            );
          
          return child;
        ,


        child: Scaffold(
          resizeToAvoidBottomPadding: false,
          appBar: AppBar(
              title: Text("Home")
          ),
          body: new Column(
            children: <Widget>[
              new Container(
                decoration: new BoxDecoration(color: Theme.of(context).cardColor),
                child: _buildTxtSearchBox(),
              ),
              new Divider(height: 10.0),
              new FloatingActionButton.extended(
                icon: Icon(Icons.camera_alt),
              ),
              new Container(
              ... 
              ),
            ],
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
          drawer: MenuDrawer(),
        )
    );
  

【讨论】:

这看起来不错,但我很困惑为什么必须有一个子属性而不是仅仅在构建器中返回小部件。这样,所有小部件都可以访问连接结果【参考方案3】:

connectivity 包可以满足您的需求。它有一个您可以订阅的onConnectivityChanged 流。这将在连接状态更改时通知您的应用。但仅仅因为您的设备连接到网络并不意味着它可以访问您的服务器并连接。因此,在更新应用程序的内部状态之前进行 DNS 查找是一个好主意。

https://pub.dartlang.org/documentation/connectivity/latest/connectivity/Connectivity-class.html

【讨论】:

这是唯一的选择吗?【参考方案4】:

我认为这是可靠且更有说服力的:

Future<bool> connectivityChecker() async 
  var connected = false;
  print("Checking internet...");
  try 
    final result = await InternetAddress.lookup('google.com');
    final result2 = await InternetAddress.lookup('facebook.com');
    final result3 = await InternetAddress.lookup('microsoft.com');
    if ((result.isNotEmpty && result[0].rawAddress.isNotEmpty) ||
        (result2.isNotEmpty && result2[0].rawAddress.isNotEmpty) ||
        (result3.isNotEmpty && result3[0].rawAddress.isNotEmpty)) 
      print('connected..');
      connected = true;
     else 
      print("not connected from else..");
      connected = false;
    
   on SocketException catch (_) 
    print('not connected...');
    connected = false;
  
  return connected;

根据返回的连接的布尔值,我会运行一个基于计时器的循环来再次检查互联网,直到它连接。接受任何建议

【讨论】:

以上是关于如何在 Flutter 上持续检查互联网连接与否?的主要内容,如果未能解决你的问题,请参考以下文章

不断检查 Flutter 应用程序上的互联网断开连接

Flutter:如何检查互联网连接? [复制]

Flutter:如何使用 Firestore 检查连接性

如何使用 HTTP 请求(Flutter/Dart)检查 Internet 连接?

Flutter:检查互联网连接并根据输出导航?

**已解决** 在 dart、flutter 应用程序中检查或连续收听互联网连接/网络连接