Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Firestore не может получить данные после повторного подключения к Интернету

Автор вопроса: Matthieu EsnaultОтветов: 5

Я использую Firestore с Android SDK (11.6.2), и у меня возникает исключение, когда мое устройство было отключено и повторно подключается к Интернету.

При запросе документа firestore завершается ошибкой со следующим исключением задачи:

com.google.firebase.firestore.FirebaseFirestoreException: не удалось получить документ, поскольку клиент отключен.

Однако устройство подключено, я могу делать сетевые запросы помимо использования Firestore, и они преуспевают. Эта ошибка непоследовательна, иногда запрос выполняется сразу после повторного подключения к Интернету. Иногда запрос снова и снова терпит неудачу, затем выполняется успешно, иногда более чем через минуту после повторного подключения устройства к Интернету.

Вот пример запроса, который вызывает исключение:

val docRef = firestore.collection("foo").document("bar")
docRef.get().addOnCompleteListener { task ->
    if (task.isSuccessful) {
        Log.d("FirestoreSourceSet", "Get document success")
    } else {
        Log.e("FirestoreSourceSet", "Get document error", task.exception)
    }
}

Я не использую автономные возможности Firestore, поэтому экземпляр FirebaseFirestore инициализируется в первый раз с флагом setPersistenceEnabled(false):

val firestoreSettings = FirebaseFirestoreSettings.Builder()
    .setPersistenceEnabled(false)
    .build()

val firestore = FirebaseFirestore.getInstance().apply {
    this.firestoreSettings = firestoreSettings
}

Почему Firestore возвращает эту ошибку, даже если устройство подключено к сети? Мне что-то не хватает в конфигурации Firestore, чтобы избежать этой ошибки?

Я попытался обновить Firebase до версии 11.8.0, но столкнулся с тем же поведением.

Журналы

Это журналы при попытке получить синхронизацию некоторых данных с Firestore (которая начинается с получения документа) после выхода из режима полета: https://pastebin.com/xDMG2Pzj

Сеть уже доступна до первого вызова Firestore, так как я ждал, пока Wi-Fi установится, и проверил его с помощью ConnectivityManager Android, прежде чем продолжить работу с Firestore.

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

Первая строка журнала - это когда я включаю авиарежим, который закрывает поток Firestore.

Изменить: проблема

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

Они признали проблему, но не смогли предоставить расчетное время прибытия, поэтому нам нужно подождать:

Если мы выпустим исправление, мы объявим об этом на нашей странице примечаний к выпуску.

Это все еще проблема с firestore-core 17.0.4.

  • Есть ли значительная задержка между вызовом get() и выводом сообщения об ошибке? По моему опыту, Firestore пытается подключиться примерно в течение 30 секунд, поэтому знание задержки помогает определить, на какой фазе он находится. Я также рекомендовал бы включение ведения журнала отладки, чтобы увидеть, дает ли трафик в сети подсказку о том, почему клиент может ' т подключиться. Frank van Puffelen 10.01.2018
  • В большинстве случаев задержка между вызовом и ошибкой составляет от 4 до 5 секунд. Иногда это меньше секунды, иногда до 10 секунд. Я включил ведение журнала и обновил им свой пост. Matthieu Esnault 07.02.2018
  • У меня тоже есть эта проблема на Android, хотя я использую постоянство в автономном режиме. Есть ли в этом прогресс? Arctic45 12.04.2018
  • Та же проблема. Есть новости с их стороны? Sirelon 29.05.2018
  • Столкнувшись с той же проблемой. Любые обновления? Swapnil 02.09.2018
  • К сожалению, у меня нет обновлений по этому поводу. Об исправлении будет объявлено в примечаниях к выпуску, когда оно станет доступным, но у нас нет ETA. Проблема все еще присутствует при использовании firestore-core 17.0.4 Matthieu Esnault 03.09.2018

androidgoogle-cloud-firestore

Ответы

Ответ 1 · рейтинг 5 · Alex Mamo

Из официальной документации:

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

При инициализации Cloud Firestore вы можете включить или отключить сохранение в автономном режиме. Итак, при использовании следующей строки кода:

val firestoreSettings = FirebaseFirestoreSettings.Builder()
    .setPersistenceEnabled(false)
    .build()

Фактически вы устанавливаете постоянство на false, вы отключаете эту функцию. Чтобы решить эту проблему, просто удалите эту строку кода. По умолчанию Firestore имеет .setPersistenceEnabled(true).

Ответ 2 · рейтинг 2 · Matthieu Esnault

Эта проблема была устранена в выпуске 17.1.5 Cloud Firestore.

См. Официальный журнал изменений https://firebase.google.com/support/release-notes/android

Cloud Firestore теперь быстрее восстанавливается после плохого состояния сети.


При использовании моего проекта воспроизведения с версией 18.0.0 проблемы действительно нет.

Ответ 3 · рейтинг 1 · Sven Jacobs

Я сталкиваюсь с той же проблемой с 2018 года и пока не нашел подходящего решения. Это все еще происходит с версией 22.1.2 библиотеки Firestore для Android. Как прокомментировано в исходный код DocumentReference, это исключение выдается, когда клиент находится в автономном режиме и запрошенный документ недоступен в локальном кэше. Также есть недавнее объяснение этого поведения, написанное Денвер Конибер.

Это исключение может возникнуть для DocumentReference.get() вызовов. Вот пример трассировки стека:

com.google.firebase.firestore.FirebaseFirestoreException: Failed to get document because the client is offline.
       at com.google.firebase.firestore.DocumentReference.lambda$getViaSnapshotListener$1(DocumentReference.java:331)
       at com.google.firebase.firestore.DocumentReference$$Lambda$2.onEvent(DocumentReference.java:8)
       at com.google.firebase.firestore.DocumentReference.lambda$addSnapshotListenerInternal$2(DocumentReference.java:504)
       at com.google.firebase.firestore.DocumentReference$$Lambda$3.onEvent(DocumentReference.java:16)
       at com.google.firebase.firestore.core.AsyncEventListener.lambda$onEvent$0(AsyncEventListener.java:42)
       at com.google.firebase.firestore.core.AsyncEventListener$$Lambda$1.run(AsyncEventListener.java:2)
       at com.google.firebase.firestore.util.Executors$$Lambda$1.execute(Executors.java)
       at com.google.firebase.firestore.core.AsyncEventListener.onEvent(AsyncEventListener.java:39)
       at com.google.firebase.firestore.core.QueryListener.raiseInitialEvent(QueryListener.java:176)
       at com.google.firebase.firestore.core.QueryListener.onViewSnapshot(QueryListener.java:95)
       at com.google.firebase.firestore.core.EventManager.addQueryListener(EventManager.java:97)
       at com.google.firebase.firestore.core.FirestoreClient.lambda$listen$6(FirestoreClient.java:160)
       at com.google.firebase.firestore.core.FirestoreClient$$Lambda$6.run(FirestoreClient.java:12)
       at com.google.firebase.firestore.util.AsyncQueue.lambda$enqueue$2(AsyncQueue.java:436)
       at com.google.firebase.firestore.util.AsyncQueue$$Lambda$2.call(AsyncQueue.java:1)
       at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1(AsyncQueue.java:322)
       at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run(AsyncQueue.java:1)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(AsyncQueue.java:229)
       at java.lang.Thread.run(Thread.java:919)

Прошу прощения, если этот ответ не решит проблему, но эта информация была бы слишком длинной для комментария к исходному сообщению.

Ответ 4 · Ivan Natalchenko

У меня тоже такая же проблема. Есть обходной путь - приложение ждет некоторое время и делает еще одну попытку получить данные с сервера.

Вот макет (это Flutter / dart):

   List<Course> items;

   Widget build(BuildContext context) {
    ...
    loadData();
    ...
    //building th UI with data from items list
    ...
   }


    loadData() async {
        //is not loaded but there is internet connection
        if (!isLoaded&&isConnected) {
          try {
              querySnapshot = await query.getDocuments(source: Source.server);
            }
            catch (ex) {
              print(ex);
              Future.delayed(Duration(seconds: 10), () {
              // setState to trigger build 10 seconds later to make one more attempt
                  setState(() {
                      isLoaded = false;
                  });
              });
          return;
        }
    // here goes the code to handle the result
    items =  querySnapshot.documents.map((s) => Course.fromDb(s)).toList();
    }

Ответ 5 · Mhmd Yaseen

это может помочь

Джава:

FirebaseFirestore db = FirebaseFirestore.getInstance();

//to reconnect
db.terminate();
db = FirebaseFirestore.getInstance();

Котлин:

var db = Firebase.firestore

//to reconnect
db.terminate()
db = Firebase.firestore

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы