Docs Menu
Docs Home
/ /
Device Sync - Flutter SDK

Administrar suscripciones de sincronización - SDK de Flutter

Atlas Device Sync con Flexible Sync utiliza suscripciones y permisos para determinar qué datos sincronizar entre Atlas y su aplicación.

Puede agregar, actualizar y eliminar suscripciones de consultas para determinar qué datos se sincronizan con el dispositivo cliente.

Nota

Requisitos previos de sincronización flexible

Para habilitar la sincronización flexible en su aplicación, se requiere un clúster Atlas no fragmentado en ejecución MongoDB 5.0 o superior

Para usar Flexible Sync en una aplicación Flutter:

  1. Configurar la sincronización flexible en el backend de Atlas App Services

  2. Inicializar el cliente de la aplicación

  3. Autenticar un usuario en el cliente

  4. Abra el reino sincronizado en el cliente

Las consultas de suscripción del lado del cliente deben estar alineadas con la configuración de sincronización del dispositivo en su aplicación de servicios de aplicaciones de backend.

Sus consultas de suscripción pueden:

Novedad en la versión1.6.0 v.

Flutter v1.6.0 agrega APIs experimentales que se suscriben y se desuscriben de los resultados de una query. Estas API abstraen los detalles de añadir y remover suscripciones manualmente.

Para todas las suscripciones, necesitas un usuario autenticado y un reino sincronizado.

Si necesita más control sobre las suscripciones por motivos de optimización del rendimiento o de lógica empresarial, puede administrar manualmente el conjunto de suscripciones mediante subscriptions API. Consulte la sección "Consideraciones de rendimiento" en esta página para obtener más información.

Puedes suscribirte al RealmResults de una consulta mediante el método subscribe(). Al llamarlo, el SDK crea la nueva suscripción y la añade MutableSubscriptionSet al, de forma similar a la creación manual de una suscripción.

Opcionalmente, puede pasar un nombre de suscripción único para la consulta. Si agrega una suscripción con el mismo nombre que una suscripción existente, el SDK la sobrescribirá.

Si no se especifica un nombre de suscripción, este se establece en null y el identificador de la suscripción se basa en la cadena de consulta. Esto significa que cada vez que cambia la cadena de consulta, subscribe() crea una nueva suscripción.

Para suscribirse a una consulta, pase los siguientes argumentos a subscribe():

  • RealmResults query: Obligatorio. Un RealmResults objeto que puede crearse mediante el lenguaje de consulta Realm.

  • String name: Opcional. Nombre de la suscripción al que puedes referenciar.

  • bool update: Opcional. Si es verdadero, al agregar una suscripción con un nombre existente, se reemplaza la consulta existente por la nueva. Si es falso, el SDK genera una excepción para suscripciones duplicadas. Úselo solo con suscripciones con nombre.

En el siguiente ejemplo, nos suscribimos a dos nuevas consultas con nombre.

final boatQuery = realm.all<Boat>();
final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final boatSubscription = await boatQuery.subscribe(name: "boats");
final planeSubscription =
await bigPlaneQuery.subscribe(name: "big-planes");

Tip

Especifique un nombre de suscripción

Le recomendamos que siempre especifique un nombre de suscripción, especialmente si su aplicación utiliza varias. Esto facilita la búsqueda y la gestión de sus suscripciones.

Al suscribirse a los resultados de una consulta, estos no contienen objetos hasta que se descargan los datos sincronizados. Si necesita esperar a que se descarguen los objetos sincronizados, configure la opción waitForSyncMode.

Este ejemplo utiliza la opción firstTime, que es el comportamiento predeterminado. Una suscripción con el comportamiento firstTime solo espera a que finalice la sincronización al crearse la suscripción.

final bigPlaneQuery = realm.query<Plane>("numSeats > 100");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "firstTimeSync",
waitForSyncMode: WaitForSyncMode.firstTime,
);

Las otras opciones admitidas waitForSyncMode son:

  • always: Espera a que se descarguen los objetos coincidentes cada vez que se inicia la aplicación. La aplicación debe tener conexión a internet cada vez que se inicia.

  • neverNo esperes para descargar los objetos coincidentes. La aplicación necesita conexión a internet para que el usuario se autentique la primera vez que se inicia, pero puede abrirse sin conexión en los siguientes inicios usando credenciales en caché.

Opcionalmente, puedes especificar un token de cancelación para limitar cuánto tiempo sigue ejecutar la sincronizar descargar:

final bigPlaneQuery = realm.query<Plane>("numSeats > 200");
final planeSubscription = await bigPlaneQuery.subscribe(
name: "alwaysWaitSync",
waitForSyncMode: WaitForSyncMode.always,
cancellationToken: TimeoutCancellationToken(Duration(seconds: 5)),
);

Las suscripciones persisten entre sesiones de usuario a menos que las canceles. Puedes cancelar la suscripción a los resultados de una consulta mediante unsubscribe().

Esto elimina la suscripción de la lista de suscripciones activas, de forma similar a eliminarla manualmente. Tenga en cuenta que la lista de resultados puede seguir conteniendo objetos después de llamar unsubscribe() a si existe otra suscripción con objetos superpuestos.

Al llamar a unsubscribe() en una consulta, el SDK elimina cualquier suscripción con consultas que coincidan exactamente con la consulta en la que se llama a unsubscribe(). Este método retorna antes de que se eliminen del dominio los objetos que coinciden con la suscripción eliminada. La sincronización continúa en segundo plano según el nuevo conjunto de suscripciones.

planeQuery.unsubscribe();
trainQuery.unsubscribe();

Al configurar la sincronización flexible en el backend, se especifican los campos que la aplicación cliente puede consultar. En la aplicación cliente, se utiliza la propiedad Realm.subscriptions para administrar un conjunto de suscripciones a consultas específicas en campos consultables.

Puedes hacer lo siguiente con tus suscripciones:

  • Obtenga una lista de todas las suscripciones

  • Añadir suscripciones

  • Comprobar el estado de la suscripción

  • Actualizar una suscripción con una nueva query

  • Eliminar suscripciones

Cuando los datos coinciden con la suscripción y el usuario autenticado tiene los permisos adecuados, Device Sync sincroniza los datos del backend con la app del cliente.

Los conjuntos de suscripciones persisten entre sesiones, incluso si ya no se incluye la suscripción en el código. La información de la suscripción se almacena en el archivo de base de datos del dominio sincronizado. Debe eliminar explícitamente una suscripción para que deje de intentar sincronizar los datos coincidentes.

Puede especificar un nombre de cadena para su suscripción. Si no le asigna un nombre, este se establece en null.

Al crear una suscripción, Realm busca datos que coincidan con una consulta sobre un tipo de objeto específico. En sus suscripciones de Sincronización Flexible, puede tener suscripciones sobre varios tipos de objeto diferentes o varias consultas sobre el mismo tipo de objeto.

Al utilizar Flexible Sync, puede acceder a un SubscriptionSet, una colección de suscripciones, a través de la Realm.subscriptions propiedad.

Puede utilizar este conjunto de suscripciones para agregar consultas a esta lista de suscripciones y actualizar las suscripciones existentes, como se muestra en los ejemplos a continuación.

final subscriptions = realm.subscriptions;

Debe realizar todas las mutaciones en las suscripciones establecidas dentro de un bloque de actualización. Para crear un bloque de actualización, llame a SubscriptionSet.update().

La función de devolución de llamada del bloque de actualización incluye un objeto MutableSubscriptionSet() como argumento. Puede modificar su método en SubscriptionSet para agregar una consulta a la suscripción.

Importante

Flexible Sync no admite todos los operadores disponibles en el lenguaje de consulta Realm. Consulte las limitaciones de Flexible Sync RQL para obtener más información.

El método MutableSubscriptionSet.add() toma tres argumentos:

  • RealmResults query: Obligatorio. Un RealmResults objeto que puede crearse mediante la consulta del lenguaje de consulta Realm.

  • String name: Opcional. Nombre de la suscripción al que puedes referenciar.

  • bool update: Opcional. Si es verdadero, al agregar una suscripción con un nombre existente, se reemplaza la consulta existente por la nueva. Úselo solo con suscripciones con nombre.

Nota

Suscripciones duplicadas

Si agrega una suscripción duplicada sin nombre con la misma consulta, Realm la elimina automáticamente; agregar una suscripción con el mismo nombre no es una operación. Por lo tanto, en ambos casos, las suscripciones duplicadas se ignoran.

Puede agregar una sola consulta o agrupar varias consultas dentro de un bloque SubscriptionSet.update. Actualizar las consultas es una operación costosa para el servidor. Le recomendamos encarecidamente que diseñe su aplicación para minimizar las actualizaciones de suscripciones. Puede lograrlo creando todas las suscripciones en un único bloque de actualización la primera vez que el usuario inicia la aplicación y agrupando los cambios posteriores en el conjunto de suscripciones.

En el siguiente ejemplo, nos suscribimos a dos consultas.

final planeQuery = realm.all<Plane>();
final longTrainQuery = realm.query<Train>("numCars >= 5");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(planeQuery, name: "planes");
mutableSubscriptions.add(longTrainQuery,
name: 'long-trains', update: true);
});
await realm.subscriptions.waitForSynchronization();

Puede actualizar una suscripción con nombre con una nueva consulta. Para actualizar la consulta de una suscripción, abra un bloque de actualización con SubscriptionSet.update(). En la función de devolución de llamada del bloque de actualización, pase los siguientes argumentos a MutableSubscriptionSet.add():

  • La nueva consulta

  • El nombre de la suscripción que desea actualizar

  • update: true

No se puede actualizar una suscripción sin nombre. También se puede eliminar la suscripción sin nombre y crear una nueva con la consulta deseada.

En el siguiente ejemplo, los trenes largos se redefinen como cualquier tren que tenga más de 10 vagones.

final longerTrainQuery = realm.query<Train>("numCars > 10");
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.add(longerTrainQuery,
name: 'long-trains', update: true);
});

Para eliminar suscripciones del conjunto de suscripciones, puede:

  • Eliminar una sola suscripción con la consulta indicada

  • Eliminar una sola suscripción con el nombre especificado

  • Eliminar una sola suscripción con la referencia de suscripción

  • Eliminar todas las suscripciones para un tipo de objeto Realm

  • Eliminar todas las suscripciones

Cuando elimina una consulta de suscripción, el servidor también elimina los datos sincronizados del dispositivo cliente.

Dentro de un bloque de actualización, puede eliminar una suscripción específica mediante una consulta. Abra un bloque de actualización con.SubscriptionSet.update() Pase el Subscription a MutableSubscriptionSet.removeByQuery().

En el siguiente ejemplo, se elimina la suscripción para todos los objetos Plane.

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByQuery(realm.all<Plane>());
});

Dentro de un bloque de actualización, puedes eliminar una suscripción específica por nombre. Pasa el nombre a MutableSubscriptionSet.removeByName().

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByName('long-trains');
});

Puedes eliminar una suscripción si tienes una referencia a su objeto Subscription. Dentro de un bloque de actualización de suscripción, pasa la Subscription referencia a MutableSubscriptionSet.remove().

final sub = realm.subscriptions[0];
realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.remove(sub);
});

Puedes eliminar todas las suscripciones de un tipo de objeto Realm determinado. Dentro de un bloque de actualización de suscripción, llama a MutableSubscriptionSet.removeByType().

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.removeByType<Train>();
});

Dentro de un bloque de actualización de suscripción, puede eliminar todas las suscripciones sin nombre del conjunto de suscripciones con MutableSubscriptionSet.clear().

realm.subscriptions.update((MutableSubscriptionSet mutableSubscriptions) {
mutableSubscriptions.clear();
});

Modificar el conjunto de suscripciones dentro de un bloque de actualización es solo una parte del proceso de cambio de una suscripción. Tras el cambio de suscripción local, el dominio se sincroniza con el servidor para resolver cualquier actualización de datos debida al cambio de suscripción. Esto incluye añadir o eliminar datos del dominio sincronizado.

Utilice Realm.subscriptions.waitForSynchronization() para esperar a que el servidor confirme este conjunto de suscripciones. Si el servidor rechaza el cambio, se genera una excepción.

Puede ocurrir una excepción si:

  • Te suscribes a una consulta no compatible. Suscribirte a una consulta no compatible pausará la sincronización. Para reanudarla, elimina la consulta no compatible.

  • Está realizando una acción no válida, como agregar un objeto que no coincide con una suscripción. Esto activa un reinicio del cliente: se borran los datos del dominio y se crea una nueva copia sin ninguna suscripción en el conjunto.

await realm.subscriptions.waitForSynchronization();

Utilice la propiedad Realm.subscriptions.state para leer el estado actual del conjunto de suscripciones.

El superseded estado es un SubscriptionSetState que puede ocurrir cuando otro subproceso actualiza una suscripción en una instancia diferente del conjunto de suscripciones. Si el estado cambia superseded a, debe obtener una nueva instancia del conjunto de suscripciones para poder actualizarlo.

Nota

Estado de suscripción "Completado"

El estado "Completado" del conjunto de suscripción no significa que la sincronización esté completa ni que todos los documentos se hayan sincronizado. "Completado" significa que han ocurrido las dos cosas siguientes:

  • La suscripción se ha convertido en el conjunto de suscripciones activas que actualmente se está sincronizando con el servidor.

  • Los documentos que coincidían con la suscripción en el momento de enviarla al servidor se encuentran ahora en el dispositivo local. Tenga en cuenta que esto no incluye necesariamente todos los documentos que coinciden actualmente con la suscripción.

El SDK de Realm no proporciona una manera de verificar si todos los documentos que coinciden con una suscripción se han sincronizado con el dispositivo.

Añadir un campo consultable indexado a tu aplicación puede mejorar el rendimiento de consultas simples sobre datos con particiones estrictas. Por ejemplo, una aplicación donde las consultas asignan datos de forma estricta a un dispositivo, tienda o usuario,user_id == $0, “641374b03725038381d2e1fb” como, es una buena candidata para un campo consultable indexado. Sin embargo, un campo consultable indexado tiene requisitos específicos para su uso en una suscripción de consultas:

  • El campo consultable indexado debe usarse en todas las consultas de suscripción. No puede faltar en la consulta.

  • El campo consultable indexado debe usar una comparación == o IN con una constante al menos una vez en la consulta de suscripción. Por ejemplo, user_id == $0, "641374b03725038381d2e1fb" o store_id IN $0, {1,2,3}.

Opcionalmente, puede incluir una comparación AND siempre que el campo consultable indexado se compare directamente con una constante usando == o IN al menos una vez. Por ejemplo, store_id IN {1,2,3} AND region=="Northeast" o store_id == 1 AND (active_promotions < 5 OR num_employees < 10).

Las consultas de sincronización flexibleno válidas en un campo consultable indexado incluyen consultas donde:

  • El campo consultable indexado no usa AND con el resto de la consulta. Por ejemplo, store_id IN {1,2,3} OR region=="Northeast" no es válido porque usa OR en lugar de AND. De igual manera, store_id == 1 AND active_promotions < 5 OR num_employees < 10 no es válido porque AND solo se aplica al término contiguo, no a toda la consulta.

  • El campo consultable indexado no se utiliza en un operador de igualdad. Por ejemplo, store_id > 2 AND region=="Northeast" no es válido porque solo utiliza el operador > con el campo consultable indexado y no tiene una comparación de igualdad.

  • A la consulta le falta por completo el campo consultable indexado. Por ejemplo, region=="Northeast o truepredicate no son válidos porque no contienen dicho campo.

La sincronización flexible presenta algunas limitaciones al usar operadores RQL. Al escribir la suscripción de consulta que determina qué datos sincronizar, el servidor no admite estos operadores. Sin embargo, aún puede usar todas las funciones de RQL para consultar el conjunto de datos sincronizados en la aplicación cliente.

Tipo de operador
Operadores no compatibles

Operadores agregados

@avg, @count, @max, @min, @sum

Sufijos de consulta

DISTINCT, SORT, LIMIT

Las consultas que no distinguen entre mayúsculas y minúsculas ([c]) no pueden usar índices eficazmente. Por lo tanto, no se recomiendan, ya que podrían causar problemas de rendimiento.

Flexible Sync solo admite @count para campos de matriz.

Flexible Sync admite la consulta de listas mediante el operador IN.

Puede consultar una lista de constantes para ver si contiene el valor de un campo consultable:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

Si un campo consultable tiene un valor de matriz, puedes consultar para ver si contiene un valor constante:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

Advertencia

No se pueden comparar dos listas en una consulta de sincronización flexible. Tenga en cuenta que esta sintaxis del lenguaje de consulta de dominio es válida fuera de las consultas de sincronización flexible.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

La sincronización flexible no admite consultas sobre propiedades en objetos incrustados ni enlaces. Por ejemplo, obj1.field == "foo".

El límite de tamaño para cualquier suscripción de consulta en su conjunto de suscripciones es de kB. Superar este límite genera 256 un error "LimitsExceeded".

Administrar varias suscripciones con la .subscribe() API (descrita en la sección "Suscribirse a consultas") es menos eficiente que realizar actualizaciones por lotes cuando se administran manualmente mediante la API de conjuntos de suscripciones. Para un mejor rendimiento al realizar cambios en varias suscripciones, utilice la subscriptions.update API (descrita en la sección "Administrar suscripciones manualmente").

Cada transacción de escritura para un conjunto de suscripciones tiene un coste de rendimiento. Si necesita realizar varias actualizaciones a un objeto de Realm durante una sesión, considere mantener los objetos editados en memoria hasta que se completen todos los cambios. Esto mejora el rendimiento de la sincronización al escribir solo el objeto completo y actualizado en su reino, en lugar de cada cambio.

Volver

Reino sincronizado abierto