Как обработать исключение сокета, когда нет сети? - PullRequest
0 голосов
/ 19 февраля 2019

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

Я нашел эту проблему и этот вопрос об исключениях для сокетов, но ни один из них не помог мне.

Вот как я называю свой бэкэнд API -

callBackendApi() async {
  try {
    http.Response response = await Future.value(/*api call here*/)
        .timeout(Duration(seconds: 90), onTimeout: () {
      print('TIME OUT HAPPENED');
    });
  } catch (exception) {
    Fluttertoast.showToast(msg: 'Check internet connection.');
    print('Error occurred' + exception.toString());
  }
}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Я использую дио , как это:

try {

    var formData = FormData.from(Map<String, dynamic>.from(data));

    var response = await dio.post(
      uri,
      data: formData,
    );
    jsonResponse = json.decode(response.data);
  } on DioError catch (e) {

    if (DioErrorType.RECEIVE_TIMEOUT == e.type ||
        DioErrorType.CONNECT_TIMEOUT == e.type) {
      throw CommunicationTimeoutException(
          "Server is not reachable. Please verify your internet connection and try again");
    } else if (DioErrorType.RESPONSE == e.type) {
      // 4xx 5xx response
      // throw exception...
    } else if (DioErrorType.DEFAULT == e.type) {
         if (e.message.contains('SocketException')) {
           throw CommunicationTimeoutException('blabla');
         }
    } else {
          throw CommunicationException("Problem connecting to the server. Please try again.");
    }
 }
0 голосов
/ 19 февраля 2019

Ну, я не знаю, будет ли мой ответ решить ваш вопрос, но несколько дней назад у меня была проблема, скорее всего, ваша, но в моем случае использовалась база данных Firebase в реальном времени.Я спрашивал себя, как я могу защитить свое приложение от сетевых сбоев, как, например, отсутствие доступа к интернету?Ну, я тоже не использую пакет подключения, поэтому я решаю эту проблему с помощью подхода, который вы уже пробовали использовать тайм-аут для сетевых операций.Я поделюсь двумя фрагментами с различными подходами, которые я реализовал для решения этой проблемы, добавив некоторые комментарии, пытаясь объяснить различия между ними.

Подход 1. Установка времени ожидания вне метода сетевого запроса

Итак, приведенный ниже фрагмент кода представляет собой простой запрос к базе данных Firebase, где _viewsRef - это ссылка на базу данных, а метод once выполняет запрос и возвращает мне будущее с данными или без данных.

// get users visualization from realtime database and returns a future 
static Future<DataSnapshot> getUserVisualizations({@required String uid}) async {
    return _viewsRef.child(uid).limitToLast(50).once();
  }

В моем классе компонентов BLoC я вызываю метод ниже и устанавливаю тайм-аут на будущее, которое возвращается.

myBlocComponentMethod(){
    //.. some work and finally the call
    FirebaseUserViewsHelper.getUserVisualizations(uid: _currentUid)
        .then(
            (dataSnapshot){
              if (dataSnapshot.value == null) {
                  // do some things to handle no data
              }

              else {
                  /// handle your data here
                });
              }
            } // setting timeout here is an important point 
        ).timeout( Duration(seconds: Constants.NETWORK_TIMEOUT_SECONDS),
            onTimeout: (){
                  // method to handle a timeout exception and tell to view layer that
                 // network operation fails
                 // if we do not implement onTimeout callback the framework will throw a  TimeoutException
             } );
  }

Хорошо, какой здесь смысл?В этом случае, если тайм-аут истекает, а будущее еще не завершено, вызывается обратный вызов onTimeout, и там я могу сообщить слою представления, что работа сети не удалась, и показать пользователю некоторый виджет об этом.Но даже по истечении времени ожидания запрос к базе данных firebase продолжает повторяться снова и снова, это похоже на асинхронное событие запроса, которое база данных остается в очереди событий dart.Я думаю, что это плохое поведение с точки зрения производительности, но если вы создаете свой пользовательский интерфейс с использованием StreamBuilder с небольшим количеством логики и кода, то ваши запрошенные данные будут доступны сразу же после подключения к Интернету, и с шаблоном BLoC пользовательский интерфейс может легко реагировать на это.событие, и нам не нужно предоставлять кнопку обновления в качестве примера, чтобы пользователь сделал запрос снова.Я не знаю, является ли это правильным подходом для реализации этого поведения, но оно работает.

Подход 2 - Установка таймаута внутри из метода сетевого запроса

Под другой пожарной базойметод запроса базы данных

static Future<DataSnapshot> readUserNode( {@required String uid} ) async
     => USERS_REFERENCE.child(uid).once()
          .timeout( Duration(seconds: Constants.NETWORK_TIMEOUT_SECONDS ) );
          //note: Without timeout callback this line will throw a TimeoutException if the time expires

Использование в другом компоненте BLoc:

  myBlocComponentMethod2(){
      for( String uid in  iterable ){
        FirebaseUserHelper.readUserNode(uid: uid)
            .then( (userSnapshot){

          if (userSnapshot.value == null){
            // do your stuffs
          } 

           else {
             // more stuffs to do
           }

        }).catchError( (error){
             // when timeout expired we will catch the TimeoutException HERE and handling telling
             // the UI what we need
        } );

      }
    }

Большая разница, которую я получил, заключалась в поведении.Во втором случае, так как я поместил тайм-аут в метод запроса, когда тайм-аут истекает, событие запроса больше не запускается, это похоже на то, что событие запроса было удалено из очереди событий dart.Это может быть полезно с точки зрения производительности, но теперь нам нужно предоставить кнопку обновления в пользовательском интерфейсе, чтобы пользователь снова мог выполнять данные, чтобы снова получать данные из Интернета.

Я не знаю, разрешит ли этот обходной путь вашу проблему, потому что вы рассказываете о SocketException, а не тот случай, который я описал, и я не знаю, какой API вы используете для выполнения ваших запросов.В любом случае, я надеюсь, что концепции, описанные в этом посте, помогут вам реализовать решение вашей проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...