Проверьте, доступно ли подключение к Интернету в приложении Flutter

Мне нужно выполнить сетевой вызов. Но перед этим мне нужно проверить, есть ли у устройства подключение к Интернету.

Вот что я сделал до сих пор:

  var connectivityResult = new Connectivity().checkConnectivity();// User defined class
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {*/
    this.getData();
    } else {
      neverSatisfied();
    }

Вышеуказанный метод не работает.


person Rissmon Suresh    schedule 04.04.2018    source источник


Ответы (19)


Плагин connectivity заявляет в своих документах, что он предоставляет информацию только при наличии сетевое соединение, но не если сеть подключена к Интернету

Обратите внимание, что на Android это не гарантирует подключение к Интернету. Например, приложение может иметь доступ к Wi-Fi, но это может быть VPN или Wi-Fi в отеле без доступа.

Вы можете использовать

import 'dart:io';
...
try {
  final result = await InternetAddress.lookup('example.com');
  if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
    print('connected');
  }
} on SocketException catch (_) {
  print('not connected');
}
person Günter Zöchbauer    schedule 04.04.2018
comment
Я получаю сообщение об ошибке: isNotEmpty не объявлен внутри InternetAddress - person Rissmon Suresh; 04.04.2018
comment
Упс, я уже удалил код локально, но думаю, он должен быть result[0].rawAddress.isNotEmpty. Простите за это. - person Günter Zöchbauer; 04.04.2018
comment
Я также получаю ошибки в этом коде на `on SocketException catch (_)`. Говорит, что on не определено. - person ThinkDigital; 28.05.2018
comment
Исправьте фигурные скобки: у вас 3 { и 2 }. - person Cœur; 27.06.2018
comment
Можно ли этого добиться в фоновом режиме? Как будто у меня есть очередь задач, ожидающих выполнения и ожидающих подключения к Интернету, но приложение закрыто? - person Vidor Vistrom; 06.10.2018
comment
pub.dartlang.org/packages/android_alarm_manager позволяет выполнять код в фоновом режиме (по крайней мере, на Android, на iOS немного сложнее). Я не знаю, позволяет ли он получить доступ к плагинам. - person Günter Zöchbauer; 07.10.2018
comment
Обратите внимание, что google.com недоступен внутри в Китае, и поэтому пример зависнет, если используется в Китае. Чтобы расширить свою аудиторию, избегайте использования google.com и используйте вместо него example.com. конечный результат = ждать InternetAddress.lookup ('example.com'); - person otboss; 01.03.2019
comment
У меня это не работает if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) возвращает true, если есть Wi-Fi, но нет подключения к Интернету. - person Denn; 26.04.2019
comment
@Denn Какой URL вы использовали? - person CopsOnRoad; 08.05.2019
comment
@CopsOnRoad Я использовал google.com, а также попробовал свой собственный API-адрес. имеет значение, какой я использую? - person Denn; 15.05.2019
comment
@Denn Даже я раньше не думал, имеет ли значение url, но кто-то сказал, что google.com не работает в Китае, поэтому я спросил вас. - person CopsOnRoad; 15.05.2019
comment
var result = ожидание подключения (). checkConnectivity (); дает мне ошибку, например ConnectivityService: ни у пользователя 11177, ни у текущего процесса нет android.permission.ACCESS_NETWORK_STATE., null) Кто-нибудь может помочь? - person Jay Mungara; 18.09.2019
comment
developer.android.com/training/basics/network-ops/managing Может поможет. В примере манифеста показано, как добавить разрешение. Найдите на странице .ACCESS_NETWORK_STATE - person Günter Zöchbauer; 18.09.2019
comment
@LOG_TAG не могли бы вы уточнить? - person Günter Zöchbauer; 11.10.2019
comment
@ GünterZöchbauer, извините, без подключения: ^ 0.4.3 + 2 через sdk firebase flutter firebase.google.com/docs/database/android/offline-capabilities через dart-версию database.getReference (.info / connected); возможно? - person LOG_TAG; 11.10.2019
comment
Можно ли с помощью Flutter создать приложение, похожее на Internet Speed ​​Meter? - person Sanal S; 14.10.2019
comment
На самом деле нет ограничений на то, что вы можете делать с Flutter, за исключением, возможно, таких вещей, как чистые фоновые приложения и плагины для запуска. Тем не менее, вам может потребоваться обратиться к собственным API-интерфейсам для определенных вещей. - person Günter Zöchbauer; 14.10.2019
comment
Привет, ребята, он работает, когда мы подключили его к Wi-Fi .. но у Wi-Fi нет Интернета, он все еще показывает подключение ... какое-либо решение этой проблемы? - person Zeeshan Ansari; 05.11.2019
comment
@ GünterZöchbauer, могу ли я настроить время ожидания? В моих тестах вашему коду требуется около 2,5 минут, чтобы сообщить, что пользователь отключен. - person Michel Feinstein; 20.01.2020
comment
@mFeinstein, если вы не используете await, вы получите Future, где вы можете установить тайм-аут stackoverflow.com/questions/33897140/ - person Günter Zöchbauer; 20.01.2020
comment
Ах да, совсем забыл об этом! На самом деле я думаю, что могу продолжать использовать await, я могу просто добавить .timeout после lookup(). - person Michel Feinstein; 21.01.2020
comment
Есть ли способ обнаружить изменение состояния сети без использования подключаемого модуля подключения? - person Sagar V; 03.04.2020
comment
@SagarV есть конкретная причина, по которой вы не хотите использовать плагин? - person Günter Zöchbauer; 03.04.2020
comment
Этот код работает для меня, но некоторые пользователи в моем рабочем приложении жалуются, что они не подключены, если они используют WIFI (в то время как они подключаются, если они используют сотовые данные). В чем может быть виноват? - person mactrix; 06.03.2021
comment
Почему-то код работает в эмуляторе, а не на реальном устройстве. Кто-нибудь когда-нибудь испытывал такое? - person user54517; 30.03.2021
comment
@BarnettTemwaMsiska не работает - этого обычно следует избегать при обращении за поддержкой. Может случиться так, что ваш компьютер не имеет питания, ЦРУ взломало ваш компьютер и установило шпионское ПО. Если вам нужно руководство, предоставьте правильную информацию о том, что вы пробовали, и чем результат отличается от ожидаемого. Возможно, лучше создать новый вопрос с информацией, необходимой для воспроизведения. - person Günter Zöchbauer; 29.04.2021
comment
Поскольку у меня есть пользователи в Китае, я понял, что google.com забанен в Китае. Поэтому я советую вам использовать другой сайт, чтобы проверить, есть ли у пользователя подключение к Интернету. Лично я использую example.com - person bulgarian-beast; 03.05.2021
comment
Я не могу поймать SocketException - person vannak; 27.05.2021
comment
просто любопытно, example.com использует небезопасное http-соединение. не будет ли это проблемой в производственной среде, если вы отключите небезопасные соединения? - person Norbert; 07.06.2021
comment
Я не подключаюсь, просто пытается разрешить имя хоста. Предполагается, что у него есть подключение к Интернету, если он получает IP. - person Günter Zöchbauer; 07.06.2021

Для всех, кто попадает сюда, я хотел бы добавить к ответу Гюнтера Цохбауэра, это было мое решение для реализации утилиты, чтобы знать, есть ли Интернет или нет, независимо от чего-либо еще.

Отказ от ответственности:

Я новичок в Dart и Flutter, поэтому, возможно, это не лучший подход, но я хотел бы получить отзывы.


Комбинирование flutter_connectivity и теста подключения Гюнтера Цёхбауэра

Мои требования

Я не хотел иметь кучу повторяющегося кода везде, где мне нужно было проверить соединение, и я хотел, чтобы он автоматически обновлял компоненты или что-нибудь еще, что заботится о соединении всякий раз, когда происходило изменение.

ConnectionStatusSingleton

Сначала мы настраиваем синглтон. Если вы не знакомы с этим шаблоном, в Интернете есть много полезной информации о них. Но суть в том, что вы хотите создать единственный экземпляр класса в течение жизненного цикла приложения и иметь возможность использовать его где угодно.

Этот синглтон подключается к flutter_connectivity и отслеживает изменения подключения, затем проверяет сетевое подключение, а затем использует StreamController для обновления всего, что имеет значение.

Это выглядит так:

import 'dart:io'; //InternetAddress utility
import 'dart:async'; //For StreamController/Stream

import 'package:connectivity/connectivity.dart';

class ConnectionStatusSingleton {
    //This creates the single instance by calling the `_internal` constructor specified below
    static final ConnectionStatusSingleton _singleton = new ConnectionStatusSingleton._internal();
    ConnectionStatusSingleton._internal();

    //This is what's used to retrieve the instance through the app
    static ConnectionStatusSingleton getInstance() => _singleton;

    //This tracks the current connection status
    bool hasConnection = false;

    //This is how we'll allow subscribing to connection changes
    StreamController connectionChangeController = new StreamController.broadcast();

    //flutter_connectivity
    final Connectivity _connectivity = Connectivity();

    //Hook into flutter_connectivity's Stream to listen for changes
    //And check the connection status out of the gate
    void initialize() {
        _connectivity.onConnectivityChanged.listen(_connectionChange);
        checkConnection();
    }

    Stream get connectionChange => connectionChangeController.stream;

    //A clean up method to close our StreamController
    //   Because this is meant to exist through the entire application life cycle this isn't
    //   really an issue
    void dispose() {
        connectionChangeController.close();
    }

    //flutter_connectivity's listener
    void _connectionChange(ConnectivityResult result) {
        checkConnection();
    }

    //The test to actually see if there is a connection
    Future<bool> checkConnection() async {
        bool previousConnection = hasConnection;

        try {
            final result = await InternetAddress.lookup('google.com');
            if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
                hasConnection = true;
            } else {
                hasConnection = false;
            }
        } on SocketException catch(_) {
            hasConnection = false;
        }

        //The connection status changed send out an update to all listeners
        if (previousConnection != hasConnection) {
            connectionChangeController.add(hasConnection);
        }

        return hasConnection;
    }
}

использование

Инициализация

Сначала мы должны убедиться, что мы вызываем инициализацию нашего синглтона. Но только один раз. Это зависит от вас, но я сделал это в main() своего приложения:

void main() {
    ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
    connectionStatus.initialize();

    runApp(MyApp());

    //Call this if initialization is occuring in a scope that will end during app lifecycle
    //connectionStatus.dispose();   
}

В Widget или в другом месте

import 'dart:async'; //For StreamSubscription

...

class MyWidgetState extends State<MyWidget> {
    StreamSubscription _connectionChangeStream;

    bool isOffline = false;

    @override
    initState() {
        super.initState();

        ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
        _connectionChangeStream = connectionStatus.connectionChange.listen(connectionChanged);
    }

    void connectionChanged(dynamic hasConnection) {
        setState(() {
            isOffline = !hasConnection;
        });
    }

    @override
    Widget build(BuildContext ctxt) {
        ...
    }
}

Надеюсь, кто-то еще найдет это полезным!


Пример репозитория github: https://github.com/dennmat/flutter-connectiontest-example

Переключите режим полета в эмуляторе, чтобы увидеть результат

person dennmat    schedule 19.12.2018
comment
Я поместил первый код в Main.dart и попытался использовать HomePage, но при этом выдает следующую ошибку: «Не удалось загрузить исходный код dart: async / broadcast_stream_controller.dart»: ‹источник недоступен›. - person Rajesh Jr.; 20.12.2018
comment
Вероятно, есть еще одна ошибка, и это просто редактор пытается открыть файл, но не имеет к нему доступа. Я изменил этот пример из своего кода, чтобы обобщить его. Может что-то сломал. Я проверю, когда вернусь домой. Но если вы посмотрите на панель отладки, сможете ли вы найти настоящую ошибку? - person dennmat; 20.12.2018
comment
Протестировал код, и он работает для меня, мне нужна дополнительная информация, чтобы помочь. - person dennmat; 21.12.2018
comment
Я тоже пробовал сейчас, но он выдает ту же ошибку. Не могли бы вы сделать образец приложения флаттера в github? - person Rajesh Jr.; 21.12.2018
comment
Ах, хорошо, я это вижу. Итак, еще раз для справки в будущем: ошибка, которую вы публикуете, - это просто попытка редактора открыть файл, в котором, по его мнению, произошла ошибка. Настоящая ошибка должна быть доступна в консоли отладки редактора / панели трассировки стека. Итак, я предполагаю, что runApp вернет, я предполагал, что он будет работать в течение всей жизни программы. Учитывая, что это в основном, удаление здесь действительно не нужно, поэтому просто удалите connectionStatus.dispose(), предполагая, что вы настраиваете его в main(), как указано выше. Обновим пост и ссылку на пример на github. - person dennmat; 21.12.2018
comment
теперь ошибка исчезла, но ошибки есть, когда я переключаюсь с одного Wi-Fi на другой Wi-Fi, он обнаруживает подключение к Интернету Actvie, но остается на том же Wi-Fi, я отключил Интернет, .. он не обнаруживает изменений, .. - person Rajesh Jr.; 21.12.2018
comment
Чтобы просто определить, переключается ли Wi-Fi или сотовая связь, вам нужно только соединение с флаттером. Эта оболочка проверяет соединение после переключения. Но не будет предупреждать каждое изменение сети. Если вы используете эмулятор, переключение режима полета - это самый простой способ потерять подключение к Интернету. Если вы используете реальное устройство, вам нужно убедиться, что вы все еще не подключены к мобильной сети с данными. - person dennmat; 21.12.2018
comment
Мое четкое требование - обнаруживать изменения ЖИВОГО АКТИВНОГО ПОДКЛЮЧЕНИЯ К ИНТЕРНЕТУ, такие как приложения youtube и google go, но для этого не найдено решений, я пробовал передавать результаты http, ни одно из них не помогло - person Rajesh Jr.; 23.12.2018
comment
Для этого есть несколько вариантов, вы можете изменить приведенное выше, чтобы использовать таймер для частого тестирования. Или просто часто тестируйте с помощью утилиты Timer. См. api.dartlang.org/stable/2.1. 0 / dart-async / Timer-class.html Другой вариант - проверять соединение перед каждым отправляемым запросом. Хотя похоже, что вы можете искать что-то вроде веб-сокетов. В любом случае удачи - person dennmat; 29.12.2018
comment
Виджет @dennmat отображается как подключенный. когда я открываю приложение при отключенном соединении. Вы можете это проверить? - person ChyperX; 30.12.2018
comment
Вероятно, это из-за того, что первая проверка происходит еще до того, как компонент существует, и в моем примере по умолчанию он думает, что он онлайн. Вместо этого вы можете присвоить !mySingletonInstance.hasConnection значение по умолчанию isOffline. - person dennmat; 06.01.2019
comment
Действительно ли нужно сохранять _connectionChangeStream в состоянии? Мой линтер показывает предупреждение: значение поля _connectionChangeStream не используется. - person Oren; 21.02.2019
comment
Разве мы не должны отменить подписку в функции виджета dispose ()? Я вижу, что это делается в других примерах StreamController, например здесь: stackoverflow.com/ questions / 44788256 / update-data-in-flutter - person Oren; 21.02.2019
comment
Я пробовал репозиторий на GitHub. Но есть баг. первая загрузка приложения без подключения к Интернету, показывающая подключено. Как исправить эту проблему? - person BloodLoss; 11.03.2019
comment
Хорошая реализация! Однако благодаря поддержке Dart переменных верхнего уровня ваш синглтон может быть намного проще: final connectionStatus = new ConnectionStatusSingleton.init(); - person Jannie Theunissen; 25.04.2019
comment
Для веб-поддержки я заменил dart.io на dio - person Stack Underflow; 08.07.2020
comment
привет, вы слушаете изменения подключения, а затем проверяете подключение к Интернету. но подключение к Интернету может быть потеряно, пока есть подключение к существующему источнику Wi-Fi или мобильному телефону. - person RL Shyam; 20.08.2020
comment
Я думаю, мы должны отменить эту строку _connectivity.onConnectivityChanged.listen(_connectionChange); на dispose. Поместите эту строку в переменную для вызова .cancel() позже в функции dispose. - person Taufik Nur Rahmanda; 11.03.2021
comment
убедитесь, что вы поместили WidgetsFlutterBinding.ensureInitialized (); как первая строка в main () - person skyllet; 25.04.2021
comment
Я попробовал решение, указанное выше, но продолжаю получать следующее сообщение об ошибке: [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Null check operator used on a null value Что указывает на ошибку в списке _connectivity.onConnectivityChanged.listen(_connectionChange); - person Aashwiin Roghan; 15.07.2021
comment
@AashwiinRoghan Да, у меня была такая же проблема, этот пост кажется старым. Я обновился с той же логикой. проверьте ниже - person codingwithtashi; 19.07.2021

введите описание изображения здесь

Полный пример, демонстрирующий слушателя подключения к Интернету и его источник.

Кредит для: connectivity и Günter Zöchbauer

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 string;
    switch (_source.keys.toList()[0]) {
      case ConnectivityResult.none:
        string = "Offline";
        break;
      case ConnectivityResult.mobile:
        string = "Mobile: Online";
        break;
      case ConnectivityResult.wifi:
        string = "WiFi: Online";
    }

    return Scaffold(
      appBar: AppBar(title: Text("Internet")),
      body: Center(child: Text("$string", style: TextStyle(fontSize: 36))),
    );
  }

  @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();
}
person CopsOnRoad    schedule 09.07.2019
comment
через firebase, SDK это возможно? - person LOG_TAG; 11.10.2019
comment
@LOG_TAG Для этого необязательно использовать Firebase. - person CopsOnRoad; 11.10.2019
comment
Карта _source = {ConnectivityResult.none: false}; Почему вы использовали здесь ложь - person Faruk AYDIN; 16.03.2020
comment
@CopsOnRoad Спасибо! Я использовал этот метод, но этот метод дает мне первый раз NoInternetConnection! Зачем сначала давать мне Ничего? Это мой отладочный отпечаток: connectivityResult.none connectivityResult.wifi connectivityResult.wifi. - person Faruk AYDIN; 17.03.2020
comment
@CopsOnRoad Но это неправда. мы не должны ждать. - person Faruk AYDIN; 17.03.2020
comment
@FarukAYDIN ​​Я удалил все свои комментарии, вы тоже можете это сделать. - person CopsOnRoad; 17.03.2020
comment
Как я могу реализовать это для всего приложения? - person Rock; 21.09.2020
comment
@Rock: мне просто нужно изменить каркас тела, похожий на этот, вернуть Scaffold (appBar: AppBar (title: Text (Internet)), body: string == Offline? IsNotConnected (): isConnected (),); - person M. Syamsul Arifin; 29.03.2021

Я обнаружил, что простого использования пакета подключения недостаточно, чтобы определить, доступен ли Интернет или нет. В Android он проверяет только наличие Wi-Fi или включение мобильных данных, но не проверяет наличие фактического подключения к Интернету. Во время моего тестирования даже при отсутствии мобильного сигнала ConnectivityResult.mobile возвращал true.

В IOS мое тестирование показало, что плагин подключения правильно определяет, есть ли подключение к Интернету, когда на телефоне нет сигнала, проблема была только в Android.

Решение, которое я нашел, заключалось в использовании пакета data_connection_checker вместе с пакетом подключения. Это просто обеспечивает подключение к Интернету, отправляя запросы на несколько надежных адресов, тайм-аут по умолчанию для проверки составляет около 10 секунд.

Моя законченная функция isInternet выглядела примерно так:

  Future<bool> isInternet() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      // I am connected to a mobile network, make sure there is actually a net connection.
      if (await DataConnectionChecker().hasConnection) {
        // Mobile data detected & internet connection confirmed.
        return true;
      } else {
        // Mobile data detected but no internet connection found.
        return false;
      }
    } else if (connectivityResult == ConnectivityResult.wifi) {
      // I am connected to a WIFI network, make sure there is actually a net connection.
      if (await DataConnectionChecker().hasConnection) {
        // Wifi detected & internet connection confirmed.
        return true;
      } else {
        // Wifi detected but no internet connection found.
        return false;
      }
    } else {
      // Neither mobile data or WIFI detected, not internet connection found.
      return false;
    }
  }

Часть if (await DataConnectionChecker().hasConnection) одинакова как для мобильных, так и для Wi-Fi-соединений и, вероятно, должна быть вынесена в отдельную функцию. Я не делал этого здесь, чтобы сделать его более читабельным.

Это мой первый ответ о переполнении стека, надеюсь, он кому-то поможет.

person abernee    schedule 30.04.2020
comment
Добро пожаловать в stackoverflow. Просто интересно, в чем вообще преимущество перед простым использованием await DataConnectionChecker().hasConnection? - person Herbert Poul; 30.04.2020
comment
Единственная причина в том, что на IOS пакет подключения может практически мгновенно сказать, что подключения нет. Если бы я просто использовал пакет data_connection_checker, приложению на IOS пришлось бы ждать, пока истечет время ожидания HTTP-запроса, около 10 секунд, прежде чем вернуть false. Однако в некоторых случаях это может быть приемлемо. Пакет подключения также может определить, используете ли вы Wi-Fi или мобильные данные, о которых мне не нужно знать здесь, но может быть полезно знать. - person abernee; 30.04.2020
comment
Это отлично работает с небольшими изменениями синтаксиса в приведенном выше коде. 1. вам нужно изменить Future ‹Bool› на future ‹bool›), потому что типы строчные. 2. Добавьте точку с запятой (;) для 4-го последнего оператора возврата. - person TDM; 01.07.2020
comment
Спасибо TDM, ответ отредактировал с вашими доработками. - person abernee; 02.07.2020

С использованием

dependencies:
  connectivity: ^0.4.2

мы получили от ресурсов

      import 'package:connectivity/connectivity.dart';

      Future<bool> check() async {
        var connectivityResult = await (Connectivity().checkConnectivity());
        if (connectivityResult == ConnectivityResult.mobile) {
          return true;
        } else if (connectivityResult == ConnectivityResult.wifi) {
          return true;
        }
        return false;
      }

Будущее для меня немного проблематично, мы должны реализовывать его каждый раз, например:

check().then((intenet) {
      if (intenet != null && intenet) {
        // Internet Present Case
      }
      // No-Internet Case
    });

Итак, чтобы решить эту проблему, я создал класс, который принимает функцию с логическим параметром isNetworkPresent, подобную этому

methodName(bool isNetworkPresent){}

И класс полезности

import 'package:connectivity/connectivity.dart';

class NetworkCheck {
  Future<bool> check() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      return true;
    } else if (connectivityResult == ConnectivityResult.wifi) {
      return true;
    }
    return false;
  }

  dynamic checkInternet(Function func) {
    check().then((intenet) {
      if (intenet != null && intenet) {
        func(true);
      }
      else{
    func(false);
  }
    });
  }
}

И использовать утилиту проверки подключения

  fetchPrefrence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

я буду использовать этот синтаксис

NetworkCheck networkCheck = new NetworkCheck();
networkCheck.checkInternet(fetchPrefrence)
person Tushar Pandey    schedule 12.02.2019

Я создал пакет, который (я думаю) надежно решает эту проблему.

Пакет на pub.dev

Пакет на GitHub

Обсуждение очень приветствуется. Вы можете использовать трекер проблем на GitHub.


Я больше не считаю приведенный ниже метод надежным:


Хотите добавить что-нибудь в ответ @Oren: вам действительно стоит добавить еще один улов, который будет улавливать все другие исключения (просто чтобы safe), ИЛИ просто полностью удалите тип исключения и используйте уловку, которая обрабатывает все исключения:

Дело 1:

try {
  await Firestore.instance
    .runTransaction((Transaction tx) {})
    .timeout(Duration(seconds: 5));
  hasConnection = true;
} on PlatformException catch(_) { // May be thrown on Airplane mode
  hasConnection = false;
} on TimeoutException catch(_) {
  hasConnection = false;
} catch (_) {
  hasConnection = false;
}

или даже проще ...

Случай 2:


try {
  await Firestore.instance
    .runTransaction((Transaction tx) {})
    .timeout(Duration(seconds: 5));
  hasConnection = true;
} catch (_) {
  hasConnection = false;
}
person kristiyan.mitev    schedule 01.06.2019

Я сделал базовый класс для состояния виджета

Использование вместо State<LoginPage> используйте BaseState<LoginPage>, а затем просто используйте логическую переменную isOnline

Text(isOnline ? 'is Online' : 'is Offline')

Сначала добавьте плагин подключения:

dependencies:
  connectivity: ^0.4.3+2

Затем добавьте класс BaseState

import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';

import 'package:connectivity/connectivity.dart';
import 'package:flutter/widgets.dart';

/// a base class for any statful widget for checking internet connectivity
abstract class BaseState<T extends StatefulWidget> extends State {

  void castStatefulWidget();

  final Connectivity _connectivity = Connectivity();

  StreamSubscription<ConnectivityResult> _connectivitySubscription;

  /// the internet connectivity status
  bool isOnline = true;

  /// initialize connectivity checking
  /// Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initConnectivity() async {
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      await _connectivity.checkConnectivity();
    } on PlatformException catch (e) {
      print(e.toString());
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) {
      return;
    }

    await _updateConnectionStatus().then((bool isConnected) => setState(() {
          isOnline = isConnected;
        }));
  }

  @override
  void initState() {
    super.initState();
    initConnectivity();
    _connectivitySubscription = Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult result) async {
      await _updateConnectionStatus().then((bool isConnected) => setState(() {
            isOnline = isConnected;
          }));
    });
  }

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

  Future<bool> _updateConnectionStatus() async {
    bool isConnected;
    try {
      final List<InternetAddress> result =
          await InternetAddress.lookup('google.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
        isConnected = true;
      }
    } on SocketException catch (_) {
      isConnected = false;
      return false;
    }
    return isConnected;
  }
}

И вам нужно привести виджет в свое состояние следующим образом

@override
  void castStatefulWidget() {
    // ignore: unnecessary_statements
    widget is StudentBoardingPage;
  }
person amorenew    schedule 07.07.2019
comment
как я могу использовать этот класс? - person DolDurma; 26.08.2019
comment
@DolDurma Просто добавьте его и импортируйте, а затем вместо State ‹LoginPage› используйте BaseState ‹LoginPage›, а затем просто используйте логическую переменную isOnline - person amorenew; 26.08.2019
comment
с этим кодом я не могу получить ценности от widget. например: RegisterBloc get _registerBloc => widget.registerBloc; я получаю эту ошибку error: The getter 'registerBloc' isn't defined for the class 'StatefulWidget'. (undefined_getter at lib\screens\fragmemt_register\view\register_mobile_number.dart:29) см. эту реализацию: class _FragmentRegisterMobileNumberState extends BaseState<FragmentRegisterMobileNumber> with SingleTickerProviderStateMixin { RegisterBloc get _registerBloc => widget.registerBloc; - person DolDurma; 26.08.2019
comment
@DolDurma Я не уверен, в чем проблема без образца GitHub, потому что этой информации недостаточно - person amorenew; 26.08.2019
comment
пожалуйста, проверьте это репо и покажите мне, как я могу использовать is_online для входа в консоль github.com/MahdiPishguy/ образец-соединения-флаттера - person DolDurma; 28.08.2019
comment
@DolDurma просто используйте AppBar (title: Text (isOnline? 'Online': 'Offline'),) - person amorenew; 29.08.2019
comment
как я могу исправить эту ошибку? E/flutter ( 2969): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. E/flutter ( 2969): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree - person DolDurma; 05.09.2019
comment
используйте if (mount) в вашем установленном состоянии - person amorenew; 06.09.2019
comment
Я проверил это перед публикацией комментария, без каких-либо изменений :( - person DolDurma; 07.09.2019
comment
@DolDurma просто используйте (виджет как MyHomePage) .title - person amorenew; 08.09.2019

Следуя ответу @dennmatt, я заметил, что InternetAddress.lookup может возвращать успешные результаты, даже если подключение к Интернету отключено - я проверил это, подключив с симулятора на домашний Wi-Fi, а затем отключив кабель маршрутизатора. Я думаю, причина в том, что маршрутизатор кэширует результаты поиска домена, поэтому ему не нужно запрашивать DNS-серверы при каждом запросе поиска.

В любом случае, если вы используете Firestore, как я, вы можете заменить блок try-SocketException-catch пустой транзакцией и перехватить TimeoutExceptions:

try {
  await Firestore.instance.runTransaction((Transaction tx) {}).timeout(Duration(seconds: 5));
  hasConnection = true;
} on PlatformException catch(_) { // May be thrown on Airplane mode
  hasConnection = false;
} on TimeoutException catch(_) {
  hasConnection = false;
}

Также обратите внимание, что previousConnection устанавливается перед async intenet-check, поэтому теоретически, если checkConnection() вызывается несколько раз за короткое время, может быть несколько hasConnection=true в строке или несколько hasConnection=false подряд. Я не уверен, сделал ли @dennmatt это намеренно или нет, но в нашем случае побочных эффектов не было (setState вызывался только дважды с одним и тем же значением).

person Oren    schedule 21.02.2019

Пакет подключения: не гарантирует фактическое подключение к Интернету (может быть просто подключение к Wi-Fi без доступа в Интернет).

Цитата из документации:

Обратите внимание, что на Android это не гарантирует подключение к Интернету. Например, приложение может иметь доступ к Wi-Fi, но это может быть VPN или Wi-Fi в отеле без доступа.

Если вам действительно нужно проверить подключение к Интернету www, лучшим выбором будет

пакет data_connection_checker

person Andrew    schedule 29.09.2019
comment
СОГЛАСОВАНО. Вот почему объединение пакетов * Connectivity * и * Data Connection Checker * (как описано здесь - ›stackoverflow.com/a/62063600/3002719) - лучшее решение этой проблемы. - person SilSur; 04.06.2021

У меня возникла проблема с предлагаемыми решениями, использование lookup не всегда возвращает ожидаемое значение.

Это связано с кешированием DNS, значение вызова кэшируется и, если при следующей попытке выполнить правильный вызов, он возвращает кешированное значение. Конечно, это проблема, поскольку это означает, что если вы потеряете соединение и вызовете lookup, он все равно может вернуть кешированное значение, как если бы у вас был Интернет, и, наоборот, если вы повторно подключите свой Интернет после того, как lookup вернет значение null, он все равно будет возвращать значение null на время. кеша, что может занять несколько минут, даже если у вас сейчас есть Интернет.

TL; DR: lookup возврат чего-либо не обязательно означает, что у вас есть Интернет, и отсутствие возврата не обязательно означает, что у вас нет Интернета. Это ненадежно.

Я реализовал следующее решение, вдохновившись плагином data_connection_checker:

 /// If any of the pings returns true then you have internet (for sure). If none do, you probably don't.
  Future<bool> _checkInternetAccess() {
    /// We use a mix of IPV4 and IPV6 here in case some networks only accept one of the types.
    /// Only tested with an IPV4 only network so far (I don't have access to an IPV6 network).
    final List<InternetAddress> dnss = [
      InternetAddress('8.8.8.8', type: InternetAddressType.IPv4), // Google
      InternetAddress('2001:4860:4860::8888', type: InternetAddressType.IPv6), // Google
      InternetAddress('1.1.1.1', type: InternetAddressType.IPv4), // CloudFlare
      InternetAddress('2606:4700:4700::1111', type: InternetAddressType.IPv6), // CloudFlare
      InternetAddress('208.67.222.222', type: InternetAddressType.IPv4), // OpenDNS
      InternetAddress('2620:0:ccc::2', type: InternetAddressType.IPv6), // OpenDNS
      InternetAddress('180.76.76.76', type: InternetAddressType.IPv4), // Baidu
      InternetAddress('2400:da00::6666', type: InternetAddressType.IPv6), // Baidu
    ];

    final Completer<bool> completer = Completer<bool>();

    int callsReturned = 0;
    void onCallReturned(bool isAlive) {
      if (completer.isCompleted) return;

      if (isAlive) {
        completer.complete(true);
      } else {
        callsReturned++;
        if (callsReturned >= dnss.length) {
          completer.complete(false);
        }
      }
    }

    dnss.forEach((dns) => _pingDns(dns).then(onCallReturned));

    return completer.future;
  }

  Future<bool> _pingDns(InternetAddress dnsAddress) async {
    const int dnsPort = 53;
    const Duration timeout = Duration(seconds: 3);

    Socket socket;
    try {
      socket = await Socket.connect(dnsAddress, dnsPort, timeout: timeout);
      socket?.destroy();
      return true;
    } on SocketException {
      socket?.destroy();
    }
    return false;
  }

Вызов _checkInternetAccess занимает не более timeout для завершения (здесь 3 секунды), и если мы сможем достичь любого из DNS, он завершится, как только будет достигнут первый, без ожидания остальных (так как достижение одного является достаточно, чтобы знать, что у вас есть интернет). Все вызовы _pingDns выполняются параллельно.

Кажется, он хорошо работает в сети IPV4, и когда я не могу протестировать его в сети IPV6 (у меня нет доступа к одной), я думаю, что он все равно должен работать. Он также работает в сборках в режиме выпуска, но мне еще нужно отправить свое приложение в Apple, чтобы узнать, обнаружат ли они какие-либо проблемы с этим решением.

Он также должен работать в большинстве стран (включая Китай), если он не работает в одной из них, вы можете добавить DNS в список, доступный из вашей целевой страны.

person Quentin    schedule 23.06.2020

используйте connectivity_widget: ^ 0.1.7

добавить зависимости:

dependencies:
     connectivity_widget: ^0.1.7

добавить код:

           ConnectivityWidget(
            builder: (context, isOnline) => Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    "${isOnline ? 'Connected' : 'Offline'}",
                    style: TextStyle(
                        fontSize: 30,
                        color: isOnline ? Colors.green : Colors.red),
                  ),
                ],
              ),
            ),
          )

ВЫХОД:

введите описание изображения здесь

person Sandeep Pareek    schedule 16.05.2021

Ну, я прочитал почти все сообщения, и сообщение @dennmat мне наиболее полезно. хотя у меня это не сработало и тоже устарело. У меня есть обновление с обновленным пакетом flutter connectivity (т.е. connectivity_plus) и data_connection_checker (чтобы проверить, есть ли фактическое подключение к Интернету для мобильных устройств и Wi-Fi).
После этого сообщения вы сможете постоянно прослушивать подключение к Интернету.

1. Добавьте зависимости
а) connectivity_plus: ^ 1.0.6
б) data_connection_checker: ^ 0.3.4

2. Пользовательский класс, который обрабатывает все соединения.

import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:data_connection_checker/data_connection_checker.dart'; 

class ConnectionUtil {
  //This creates the single instance by calling the `_internal` constructor specified below
  static final ConnectionUtil _singleton = new ConnectionUtil._internal();
  ConnectionUtil._internal();
  //This is what's used to retrieve the instance through the app
  static ConnectionUtil getInstance() => _singleton;
  //This tracks the current connection status
  bool hasConnection = false;
  //This is how we'll allow subscribing to connection changes
  StreamController connectionChangeController = StreamController();
  //flutter_connectivity
  final Connectivity _connectivity = Connectivity();
  void initialize() {
    _connectivity.onConnectivityChanged.listen(_connectionChange);
  }
  //flutter_connectivity's listener
  void _connectionChange(ConnectivityResult result) {
    hasInternetInternetConnection();
  }
  Stream get connectionChange => connectionChangeController.stream;
  Future<bool> hasInternetInternetConnection() async {
    bool previousConnection = hasConnection;
    var connectivityResult = await (Connectivity().checkConnectivity());
    //Check if device is just connect with mobile network or wifi
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {
      //Check there is actual internet connection with a mobile network or wifi
      if (await DataConnectionChecker().hasConnection) {
        // Network data detected & internet connection confirmed.
        hasConnection = true;
      } else {
        // Network data detected but no internet connection found.
        hasConnection = false;
      }
    }
    // device has no mobile network and wifi connection at all
    else {
      hasConnection = false;
    }
    // The connection status changed send out an update to all listeners
    if (previousConnection != hasConnection) {
      connectionChangeController.add(hasConnection);
    }
    return hasConnection;
  }
}
  1. Проверяйте связь в любом месте и прислушивайтесь к изменениям.
@override
  initState() {
    print('called');
    //Create instance
    ConnectionUtil connectionStatus = ConnectionUtil.getInstance();
    //Initialize
    connectionStatus.initialize();
    //Listen for connection change
    _connectionChangeStream = connectionStatus.connectionChange.listen((event) {
      print(event);
    });

    super.initState();
  }

Теперь проверьте журнал при переключении режима полета. вы должны получить журнал с истинным и ложным значениями.

Примечание: это не будет работать во Flutter Web, если вы хотите, чтобы он работал, используйте плагин dio или http вместо data_connection_checker.

Пример проекта можно найти здесь. Спасибо

person codingwithtashi    schedule 19.07.2021
comment
Идеально !! Спасибо - person Aashwiin Roghan; 20.07.2021

В конечном итоге я (хотя и неохотно) остановился на решении, данном @abernee в предыдущем ответе на этот вопрос. Я всегда стараюсь использовать как можно меньше внешних пакетов в своих проектах - поскольку я знаю, что внешние пакеты - единственные [потенциальные] точки отказа в создаваемом мной программном обеспечении. Поэтому установить ссылку на ДВА внешних пакета только для такой простой реализации, как эта, было для меня непросто.

Тем не менее, я взял код Abernee и изменил его, чтобы сделать его более компактным и разумным. Под разумным я имею в виду, что он потребляет мощность пакета подключения в своей функции, но затем тратит ее внутренне, не возвращение наиболее ценных выходных данных из этого пакета (т.е. идентификация сети). Итак, вот модифицированная версия решения Abernee:

import 'package:connectivity/connectivity.dart';
import 'package:data_connection_checker/data_connection_checker.dart';


// 'McGyver' - the ultimate cool guy (the best helper class any app can ask for).
class McGyver {

  static Future<Map<String, dynamic>> checkInternetAccess() async {
    //* ////////////////////////////////////////////////////////////////////////////////////////// *//
    //*   INFO: ONLY TWO return TYPES for Map 'dynamic' value => <bool> and <ConnectivityResult>   *//
    //* ////////////////////////////////////////////////////////////////////////////////////////// *//
    Map<String, dynamic> mapCon;
    final String isConn = 'isConnected', netType = 'networkType';
    ConnectivityResult conRes = await (Connectivity().checkConnectivity());
    switch (conRes) {
      case ConnectivityResult.wifi:   //* WiFi Network: true !!
        if (await DataConnectionChecker().hasConnection) {   //* Internet Access: true !!
          mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.wifi});
        } else {
          mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.wifi});
        }
        break;
      case ConnectivityResult.mobile:   //* Mobile Network: true !!
        if (await DataConnectionChecker().hasConnection) {   //* Internet Access: true !!
          mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.mobile});
        } else {
          mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.mobile});
        }
        break;
      case ConnectivityResult.none:   //* No Network: true !!
        mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.none});
        break;
    }
    return mapCon;
  }

}

Затем вы должны использовать эту статическую функцию с помощью простого вызова из любого места вашего кода следующим образом:

bool isConn; ConnectivityResult netType;
McGyver.checkInternetAccess().then(
  (mapCIA) {  //* 'mapCIA' == amalgamation for 'map' from 'CheckInternetAccess' function result.
    debugPrint("'mapCIA' Keys: ${mapCIA.keys}");
    isConn = mapCIA['isConnected'];
    netType = mapCIA['networkType'];
  }
);
debugPrint("Internet Access: $isConn   |   Network Type: $netType");

Жаль, что вам нужно установить ссылку на ДВА ВНЕШНИХ ПАКЕТА, чтобы получить эту самую базовую функциональность в своем проекте Flutter, но я думаю, что на данный момент это лучшее, что у нас есть. На самом деле я предпочитаю пакет Data Connection Checker пакету Connectivity, но (на момент публикации) в первом отсутствовала очень важная функция сетевой идентификации, которую я требую от Пакет подключения. Это причина того, что я отказался от этого подхода [временно].

person SilSur    schedule 28.05.2020

Просто пытаюсь упростить код с помощью пакета Connectivity во Flutter.

import 'package:connectivity/connectivity.dart';

var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
  // I am connected to a mobile network.
} else if (connectivityResult == ConnectivityResult.wifi) {
  // I am connected to a wifi network.
} else {
  // I am not connected to the internet
}
person devDeejay    schedule 29.02.2020
comment
Проблема с этим на Android заключается в том, что то, что вы подключены через Wi-Fi или мобильный телефон, не означает, что вы подключены к Интернету. - person Megadec; 05.03.2020
comment
@Megadec, к сожалению, да, это единственная проблема :( - person devDeejay; 05.03.2020

Вот мое решение. Он проверяет подключение к Интернету, а также подключение к данным. Надеюсь, вам понравится.

First of all add dependencies in your pubsec.yaml
dependencies:        
    data_connection_checker:
And Here Is The main.dart Of My Solution
import 'dart:async';

import 'package:data_connection_checker/data_connection_checker.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Data Connection Checker",
      home: HomePage(),
    );
  }
}

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

class _HomePageState extends State<HomePage> {
  StreamSubscription<DataConnectionStatus> listener;

  var Internetstatus = "Unknown";

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
//    _updateConnectionStatus();
      CheckInternet();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    listener.cancel();
    super.dispose();
  }

  CheckInternet() async {
    // Simple check to see if we have internet
    print("The statement 'this machine is connected to the Internet' is: ");
    print(await DataConnectionChecker().hasConnection);
    // returns a bool

    // We can also get an enum instead of a bool
    print("Current status: ${await DataConnectionChecker().connectionStatus}");
    // prints either DataConnectionStatus.connected
    // or DataConnectionStatus.disconnected

    // This returns the last results from the last call
    // to either hasConnection or connectionStatus
    print("Last results: ${DataConnectionChecker().lastTryResults}");

    // actively listen for status updates
    listener = DataConnectionChecker().onStatusChange.listen((status) {
      switch (status) {
        case DataConnectionStatus.connected:
          Internetstatus="Connectd TO THe Internet";
          print('Data connection is available.');
          setState(() {

          });
          break;
        case DataConnectionStatus.disconnected:
          Internetstatus="No Data Connection";
          print('You are disconnected from the internet.');
          setState(() {

          });
          break;
      }
    });

    // close listener after 30 seconds, so the program doesn't run forever
//    await Future.delayed(Duration(seconds: 30));
//    await listener.cancel();
    return await await DataConnectionChecker().connectionStatus;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Data Connection Checker"),
      ),
      body: Container(
        child: Center(
          child: Text("$Internetstatus"),
        ),
      ),
    );
  }
}
person Tirth Raj    schedule 03.05.2020

Я использовал пакет data_connection_checker для проверки доступа в Интернет, даже если соединение доступно через Wi-Fi или мобильное устройство, оно работает хорошо: вот код для проверки соединения:

bool result = await DataConnectionChecker().hasConnection;
if(result == true) {
   print('YAY! Free cute dog pics!');
} else {
   print('No internet :( Reason:');
   print(DataConnectionChecker().lastTryResults);
}

ознакомьтесь с пакетом, если вам нужна дополнительная информация. Пакет проверки подключения к данным

person Muhamad Haydar Jawad    schedule 01.10.2020

поздний ответ, но используйте этот пакет, чтобы проверить. Имя пакета: data_connection_checker

в вашем файле pubspec.yuml:

dependencies:
    data_connection_checker: ^0.3.4

создайте файл с именем connection.dart или любым другим именем. импортировать пакет:

import 'package:data_connection_checker/data_connection_checker.dart';

проверьте, есть ли подключение к интернету:

print(await DataConnectionChecker().hasConnection);
person Hekmat    schedule 19.04.2020

У меня возникла проблема с принятым ответом, но, похоже, это решает ответ для других. Мне нужно решение, которое может получать ответ от используемого URL-адреса, поэтому я подумал, что http отлично подойдет для этой функции, и поэтому я нашел этот ответ действительно полезным. Как проверить подключение к Интернету с помощью HTTP-запросов (Flutter / Дротик)?

person David B.    schedule 08.10.2020

Для меня я просто создаю отдельные данные в Firebase и использую future builder для ожидания данных. Здесь, вот так, вы можете проверить, не слишком ли медленное соединение, чтобы данные загружались:

FutureBuilder(
    future: _getImage(context),
    builder: (context, snapshot) {
      switch (snapshot.connectionState) {
        case ConnectionState.none:
          return Text('Press button to start.');
        case ConnectionState.active:
        case ConnectionState.waiting:
          return Container(
              height:
                  MediaQuery.of(context).size.height / 1.25,
              width:
                  MediaQuery.of(context).size.width / 1.25,
              child: Loading());
        case ConnectionState.done:
          if (snapshot.hasData) {
            return snapshot.data;
          } else {
            return FlatButton(
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) =>
                            ProfilePage()));
              },
              child: Icon(
                Icons.add_a_photo,
                size: 50,
              ),
            );
          }
        // You can reach your snapshot.data['url'] in here
      }
      return null;
    },
  ),
person jmc 1011    schedule 25.04.2021