Saltar al contenido

Capacidades fuera de línea de Firebase y addListenerForSingleValueEvent

Tenemos la respuesta a esta obstáculo, o por lo menos eso creemos. Si sigues con dudas dínoslo, que sin tardar

Solución:

Cómo funciona la persistencia

El cliente de Firebase guarda una copia de todos los datos que escuchas activamente en la memoria. Una vez que el último oyente se desconecta, los datos se eliminan de la memoria.

Si habilita la persistencia del disco en una aplicación Firebase Android con:

Firebase.getDefaultConfig().setPersistenceEnabled(true); 

El cliente de Firebase mantendrá una copia local (en el disco) de todos los datos que la aplicación escuchó recientemente.

Qué sucede cuando adjuntas un oyente

Di que tienes lo siguiente ValueEventListener:

ValueEventListener listener = new ValueEventListener() 
    @Override
    public void onDataChange(DataSnapshot snapshot) 
        System.out.println(snapshot.getValue());
    

    @Override
    public void onCancelled(FirebaseError firebaseError) 
        // No-op
    
;

Cuando agregas un ValueEventListener a una ubicación:

ref.addValueEventListener(listener); 
// OR
ref.addListenerForSingleValueEvent(listener); 

Si el valor de la ubicación está en la memoria caché del disco local, el cliente de Firebase invocará onDataChange() inmediatamente por ese valor de la memoria caché local. Si también iniciará una verificación con el servidor, para solicitar cualquier actualización del valor. Eso mayo posteriormente invocar onDataChange() de nuevo si ha habido un cambio en los datos del servidor desde la última vez que se agregaron a la memoria caché.

¿Qué pasa cuando usas addListenerForSingleValueEvent

Cuando agrega un detector de eventos de un solo valor a la misma ubicación:

ref.addListenerForSingleValueEvent(listener);

El cliente de Firebase (como en la situación anterior) invocará inmediatamente onDataChange() para el valor de la memoria caché del disco local. Va a no invocar el onDataChange() más veces, incluso si el valor en el servidor resulta ser diferente. Tenga en cuenta que aún se solicitarán datos actualizados y se devolverán en solicitudes posteriores.

Esto se trató anteriormente en ¿Cómo funciona la sincronización de Firebase con datos compartidos?

Solución y solución alternativa

La mejor solución es usar addValueEventListener(), en lugar de un detector de eventos de valor único. Un oyente de valor regular obtendrá tanto el evento local inmediato como la posible actualización del servidor.

Como solución alternativa, también puede llamar keepSynced(true) en las ubicaciones donde usa un detector de eventos de un solo valor. Esto garantiza que los datos se actualicen siempre que cambien, lo que mejora drásticamente la posibilidad de que su detector de eventos de valor único vea el valor actual.

Así que tengo una solución de trabajo para esto. Todo lo que tiene que hacer es usar ValueEventListener y eliminar el oyente después de 0,5 segundos para asegurarse de que haya obtenido los datos actualizados para entonces si es necesario. La base de datos en tiempo real tiene una latencia muy buena, por lo que es segura. Vea el ejemplo de código seguro a continuación;

public class FirebaseController {

private DatabaseReference mRootRef;
private Handler mHandler = new Handler();

private FirebaseController() 
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);

    mRootRef = FirebaseDatabase.getInstance().getReference();


public static FirebaseController getInstance() 
    if (sInstance == null) 
        sInstance = new FirebaseController();
    
    return sInstance;

Luego, algún método que le hubiera gustado usar “addListenerForSingleEvent”;

public void getTime(final OnTimeRetrievedListener listener) 
    DatabaseReference ref = mRootRef.child("serverTime");
    ref.addValueEventListener(new ValueEventListener() 
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) 
            if (listener != null) 
                // This can be called twice if data changed on server - SO DEAL WITH IT!
                listener.onTimeRetrieved(dataSnapshot.getValue(Long.class));
            
            // This can be called twice if data changed on server - SO DEAL WITH IT!
            removeListenerAfter2(ref, this);
        

        @Override
        public void onCancelled(DatabaseError databaseError) 
            removeListenerAfter2(ref, this);
        
    );


// ValueEventListener version workaround for addListenerForSingleEvent not working.
private void removeListenerAfter2(DatabaseReference ref, ValueEventListener listener) 
    mHandler.postDelayed(new Runnable() 
        @Override
        public void run() 
            HelperUtil.logE("removing listener", FirebaseController.class);
            ref.removeEventListener(listener);
        
    , 500);


// ChildEventListener version workaround for addListenerForSingleEvent not working.
private void removeListenerAfter2(DatabaseReference ref, ChildEventListener listener) 
    mHandler.postDelayed(new Runnable() 
        @Override
        public void run() 
            HelperUtil.logE("removing listener", FirebaseController.class);
            ref.removeEventListener(listener);
        
    , 500);

Incluso si cierran la aplicación antes de que se ejecute el controlador, se eliminará de todos modos. Editar: esto se puede abstraer para realizar un seguimiento de los oyentes agregados y eliminados en un HashMap usando la ruta de referencia como key y datasnapshot como valor. Incluso puede envolver un método fetchData que tenga un indicador booleano para “una vez” si esto es true haría esta solución para obtener datos una vez, de lo contrario, continuaría normalmente. ¡De nada!

Al final de todo puedes encontrar las notas de otros gestores de proyectos, tú además puedes insertar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *