Подтвердить что ты не робот

Невозможно отключить автономные данные в Firestore

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

Я добавил это в свой пользовательский Application Class:

import android.app.Application;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreSettings;

public class ApplicationClass extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        FirebaseFirestore db=FirebaseFirestore.getInstance();
        FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
                .setPersistenceEnabled(false)
                .build();
        db.setFirestoreSettings(settings);
    }
}

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

Например, отладка этого кода всегда будет показывать, что isFromCache true и documentSnapshot пуст (даже если это на стороне server - он не пуст):

usersRef.document(loggedEmail).collection("challenges_received").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot documentSnapshots) {
        boolean isFromCache=documentSnapshots.getMetadata().isFromCache();
        if (!documentSnapshots.isEmpty()) {
        }
    }
});

Это нормальное поведение?

Есть ли другой способ отключить кеш данных в Cloud Firestore?


EDIT:

Добавление: FirebaseFirestore.setLoggingEnabled(flase); (вместо кода выше) в пользовательском Application Class дает тот же результат.

4b9b3361

Ответ 1

Я просто провел несколько тестов в приложении для Android, чтобы увидеть, как это работает. Поскольку Firestore в настоящее время все еще находится в beta release и продукт может претерпеть изменения в любое время, я не могу гарантировать, что это поведение сохранится в будущем.

db.collection("tests").document("fOpCiqmUjAzjnZimjd5c").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        DocumentSnapshot documentSnapshot = task.getResult();
        System.out.println("isFromCache: " + documentSnapshot.getMetadata().isFromCache());
    }
});

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

Когда я в сети, он печатает:

isFromCache: false

Когда я не в сети, он печатает:

isFromCache: true

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

Если вместо этого я использую слушатель:

db.collection("tests").document("fOpCiqmUjAzjnZimjd5c").addSnapshotListener(new DocumentListenOptions().includeMetadataChanges(), new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
        System.out.println("listener.isFromCache: " + documentSnapshot.getMetadata().isFromCache());
    }
});

Когда я в сети, я получаю два отпечатка:

listener.isFromCache: true
listener.isFromCache: false

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

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

Редактировать: в отличие от Firebase, где для включения автономной персистенции вам нужно использовать следующую строку кода:

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

В Firestore для Android и iOS автономное сохранение enabled by default.

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

В Firestore мы находим обратное: чтобы отключить постоянство, нам нужно установить для параметра PersistenceEnabled значение false. Это означает, что вы указываете Firestore не создавать локальную копию вашей базы данных на пользовательском устройстве, что означает, что вы не сможете запрашивать вашу базу данных, если вы не подключены к серверам Firebase. Таким образом, без локальной копии вашей базы данных и, если она не будет обнаружена, будет выдано исключение. Вот почему рекомендуется использовать OnFailureListener.

Обновление (2018-06-13): Как и @TalBarda упомянул в своем ответе, теперь это возможно, начиная с обновления версии 16.0.0 SDK. Таким образом, мы можем достичь этого с помощью методов DocumentReference.get(Source source) и Query.get(Source source).

По умолчанию get() пытается предоставить обновленные данные, когда это возможно, в ожидании данных с сервера, но он может вернуть кэшированные данные или потерпит неудачу, если вы находитесь в автономном режиме и сервер не может быть подключен. Это поведение можно изменить с помощью параметра Source.

Таким образом, теперь мы можем передать в качестве аргумента DocumentReference или в Query источник, чтобы мы могли форсировать извлечение данных только с server only chache only или пытаться chache only сервер и возвращаться к кешу.

Так что-то вроде этого теперь возможно:

FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docIdRef = db.collection("tests").document("fOpCiqmUjAzjnZimjd5c");
docIdRef.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        //Get data from the documentSnapshot object
    }
});

В этом случае мы принудительно извлекаем данные только с сервера. Если вы хотите заставить данные извлекаться только из кэша, вы должны передать в качестве аргумента метод get(), Source.CACHE. Больше информации здесь.

Ответ 2

Согласно обновлению Cloud Firestore 16.0.0 SDK, теперь есть решение этой проблемы:

enter image description here


Теперь вы можете выбрать, хотите ли вы получать данные только с сервера или только из кэша, например так (например, только для сервера):

DocumentReference documentReference= FirebaseFirestore.getInstance().document("example");
documentReference.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
            //...
    }
});

Только для кэша, просто измените код выше на Source.CACHE.


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

Ответ 3

// Enable Firestore logging
    FirebaseFirestore.setLoggingEnabled(flase);
// Firestore
    mFirestore = FirebaseFirestore.getInstance();

В общем: клиент Firebase пытается минимизировать количество загружаемых данных. Но он также пытается свести к минимуму объем памяти/дискового пространства, которое он использует.

Точное поведение зависит от многих факторов, например, остался ли другой слушатель активным в этом месте и используется ли постоянство диска. Если у вас есть два прослушивателя для одних и тех же (или перекрывающихся) данных, обновления будут загружаться только один раз. Но если вы удалите последний прослушиватель для местоположения, данные для этого местоположения будут удалены из кеша (памяти и/или диска).

Не видя полного кода, трудно сказать, что произойдет в вашем случае.

Альтернативно: вы можете проверить сами, включив ведение журнала Firebase [Firebase setLoggingEnabled:YES];

попробуйте это для базы данных FireBase

  mDatabase.getReference().keepSynced(false);      
      FirebaseDatabase.getInstance().setPersistenceEnabled(false);

Ответ 4

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder().setPersistenceEnabled(false).build(); dbEventHome.setFirestoreSettings(settings);

При установке этого он всегда получает с сервера.