Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Atlas App Services

Tutorial: Sincronización de dispositivos Atlas para Flutter

Tiempo estimado para completar: 30 minutos, dependiendo de su experiencia con Flutter.

El SDK de dispositivos Atlas para Flutter permite crear aplicaciones multiplataforma con Dart y Flutter. Este tutorial se basa en la aplicación de plantilla de sincronización flexible de Flutter. flutter.todo.flex, que ilustra la creación de una aplicación de tareas pendientes. Esta aplicación permite a los usuarios:

  • Registrar su correo electrónico como una nueva cuenta de usuario.

  • Sign in to their account with their email and password (and sign out later).

  • Ver, crear, modificar y eliminar elementos de tarea.

  • View all tasks, even where the user is not the owner.

La aplicación de plantilla también proporciona un interruptor que simula el dispositivo en modo sin conexión. Este interruptor permite probar rápidamente la sincronización del dispositivo, simulando que el usuario no tiene conexión a internet. Sin embargo, es probable que este interruptor se elimine en una aplicación de producción.

Este tutorial complementa la aplicación de plantilla. Agregará un nuevo priority campo al Item modelo existente y actualizará la suscripción de Sincronización Flexible para mostrar solo elementos dentro de un rango de prioridades.

Este tutorial ilustra cómo adaptar la aplicación de plantilla a sus necesidades. Dada la estructura actual de la aplicación, no es necesario realizar este cambio.

En este tutorial aprenderás a:

  • Update a Realm object model with a non-breaking change.

  • Actualizar una suscripción de sincronización de dispositivos

  • Add a queryable field to the Device Sync configuration on the server to change which data is synchronized.

Si prefieres comenzar con tu propia aplicación en lugar de seguir un tutorial guiado, consulta la Guía deinicio rápido de Flutter. Incluye ejemplos de código copiables y la información esencial necesaria para configurar una aplicación con el SDK de Flutter.

  • Debes tener experiencia previa en la implementación de una aplicación Flutter en un emulador de Android, un simulador de iOS y/o un dispositivo físico.

  • Este tutorial comienza con una aplicación de Plantilla. Necesitas una Cuenta de Atlas, una clave API y App Services CLI para crear una aplicación de plantilla.

    • Para obtener más información sobre cómo crear una cuenta de Atlas, consulte la sección Primeros pasos con Atlas. Para este tutorial, necesita una cuenta de Atlas con un clúster de nivel gratuito.

    • También necesita una clave API de Atlas para la cuenta de MongoDB Cloud con la que desea iniciar sesión. Debe ser propietario del proyecto para crear una aplicación de plantilla mediante la CLI de App Services.

    • Para aprender más sobre cómo instalar App Services CLI, consulta Instalar App Services CLI. Después de instalar, ejecuta el comando login utilizando la clave API de tu proyecto Atlas.

Nota

Plataformas compatibles

Puedes compilar esta aplicación de tutorial en las siguientes plataformas:

  • iOS

  • Android

  • macOS

  • Windows

  • Linux

El SDK de Flutter no admite la creación de aplicaciones web.

Este tutorial se basa en la aplicación de plantilla de sincronización flexible de Flutter llamada flutter.todo.flex. Comenzamos con la aplicación predeterminada y creamos nuevas funciones a partir de ella.

Para obtener más información sobre las aplicaciones de plantilla, consulte Aplicaciones de plantilla.

Si aún no tiene una cuenta Atlas, regístrese para implementar una aplicación de plantilla.

Siga el procedimiento descrito en la guía Crear una aplicación de servicios de aplicaciones y seleccione Create App from TemplateSeleccione la plantilla Real-time Sync. Esto crea una aplicación de Servicios de Aplicaciones preconfigurada para usarla con uno de los clientes de la plantilla de Sincronización de Dispositivos.

Después de crear una aplicación plantilla, la Interfaz de Usuario muestra un modal etiquetado como Get the Front-end Code for your Template. Este modal proporciona instrucciones para descargar el código cliente de la aplicación plantilla como un archivo .zip o para usar App Services CLI y obtener el cliente.

Después de seleccionar el método .zip o la CLI de App Services, siga las instrucciones en pantalla para obtener el código de cliente. Para este tutorial, seleccione el código de cliente Dart (Flutter).

Descomprime la aplicación descargada y verás la aplicación Flutter.

Nota

La utilidad ZIP predeterminada de Windows podría mostrar el archivo .zip vacío. Si esto ocurre, use un programa de compresión de terceros disponible.

El comando de creación de aplicaciones appservices configura el backend y crea una aplicación de plantilla Flutter para que la uses como base para este tutorial.

Ejecute el siguiente comando en una ventana de terminal para crear una aplicación llamada "MyTutorialApp" que se implementa en la región US-VA con su entorno configurado en "desarrollo" (en lugar de producción o control de calidad).

appservices app create \
--name MyTutorialApp \
--template flutter.todo.flex \
--deployment-model global \
--environment development

El comando crea un nuevo directorio en su ruta actual con el mismo nombre que el valor del indicador --name.

Puedes bifurcar y clonar un repositorio de GitHub que contenga el código del cliente de sincronización de dispositivos. El código del cliente de Flutter está disponible en https://github.com/mongodb/template-app-dart-flutter-todo.

Si usa este proceso para obtener el código del cliente, debe crear una aplicación de plantilla para usarla con el cliente. Siga las instrucciones de Crear una aplicación de plantilla para usar la interfaz de usuario de Atlas App Services, la CLI de App Services o la API de administración para crear una aplicación de plantilla de backend de Device Sync.

Clona el repositorio y sigue las instrucciones en README para agregar el ID de la aplicación de backend a la aplicación Flutter.

1

Abra la aplicación de Flutter en su editor de código.

Si descargaste el cliente como archivo .zip o clonaste su repositorio de GitHub, debes insertar manualmente el ID de la aplicación de App Services en el lugar correspondiente del cliente. Sigue las instrucciones Configuration del cliente README.md para saber dónde insertar el ID de la aplicación.

2

En tu editor de código, dedica unos minutos a explorar la organización del proyecto. Se trata de una aplicación Flutter multiplataforma estándar, modificada para nuestro uso específico. En concreto, los siguientes archivos contienen usos importantes del SDK de Flutter:

Archivo
Propósito

lib/main.dart

Punto de entrada a la aplicación. Contiene enrutamiento y gestión de estado.

lib/realm/schemas.dart

Define el esquema de la base de datos Realm.

lib/realm/schemas.realm.dart

Clase de objeto Realm generada.

lib/realm/app_services.dart

Gestiona la interacción con Atlas App Services.

lib/realm/realm_services.dart

Gestiona la interacción con Realm base de datos y Atlas Device Sync.

lib/components/

Componentes de una aplicación caracterizada por widgets de Flutter.

lib/screens/

Páginas de la aplicación.

3

Sin realizar ningún cambio en el código, debería poder ejecutar la aplicación en el emulador de Android, el simulador de iOS, el dispositivo móvil físico o el emulador de escritorio.

Primero, instale todas las dependencias ejecutando lo siguiente en su terminal:

flutter pub get

Luego, conéctelo a un dispositivo y ejecute la aplicación Flutter.

Una vez que la aplicación esté ejecutándose, registre una nueva cuenta de usuario y luego agregue un nuevo elemento a su lista de tareas pendientes.

Tip

For more information on running a Flutter app with development tools, refer to the Flutter Test Drive documentation.

4

Inicie sesión en MongoDB Atlas. En la pestaña, haga Data Services clic Browse Collections en. En la lista de bases de datos, busque y expanda la todo base de datos y, a continuación, la Item colección. Debería ver el documento que creó en esta colección.

1

Now that you have confirmed everything is working as expected, we can add changes. In this tutorial, we have decided that we want to add a "priority" property to each Item so that we can filter Items by their priorities.

Para ello siga estos pasos:

  1. En el proyecto flutter.todo.flex, abra el archivo lib/realm/schemas.dart.

  2. Agregue la siguiente propiedad a la clase _Item:

    lib/realm/schemas.dart
    late int? priority;
  3. Regenerate the Item Realm object class:

    dart run realm generate
2
  1. En lib/realm/realm_services.dart, agrega lógica para establecer y actualizar priority. También agrega una clase abstracta PriorityLevel debajo de la clase RealmServices para restringir los valores posibles.

    lib/realm/realm_services.dart
    // ... imports
    class RealmServices with ChangeNotifier {
    static const String queryAllName = "getAllItemsSubscription";
    static const String queryMyItemsName = "getMyItemsSubscription";
    bool showAll = false;
    bool offlineModeOn = false;
    bool isWaiting = false;
    late Realm realm;
    User? currentUser;
    App app;
    // ... RealmServices initializer and updateSubscriptions(),
    // sessionSwitch() and switchSubscription() methods
    void createItem(String summary, bool isComplete, int? priority) {
    final newItem = Item(ObjectId(), summary, currentUser!.id,
    isComplete: isComplete, priority: priority);
    realm.write<Item>(() => realm.add<Item>(newItem));
    notifyListeners();
    }
    void deleteItem(Item item) {
    realm.write(() => realm.delete(item));
    notifyListeners();
    }
    Future<void> updateItem(Item item,
    {String? summary,
    bool? isComplete,
    int? priority}) async {
    realm.write(() {
    if (summary != null) {
    item.summary = summary;
    }
    if (isComplete != null) {
    item.isComplete = isComplete;
    }
    if (priority != null) {
    item.priority = priority;
    }
    });
    notifyListeners();
    }
    Future<void> close() async {
    if (currentUser != null) {
    await currentUser?.logOut();
    currentUser = null;
    }
    realm.close();
    }
    @override
    void dispose() {
    realm.close();
    super.dispose();
    }
    }
    abstract class PriorityLevel {
    static int severe = 0;
    static int high = 1;
    static int medium = 2;
    static int low = 3;
    }
  2. Add a new file to contain a widget to set the priority for an Item. Create the file lib/components/select_priority.dart.

    lib/components/select_priority.dart
    import 'package:flutter/material.dart';
    import 'package:flutter_todo/realm/realm_services.dart';
    class SelectPriority extends StatefulWidget {
    int priority;
    void Function(int priority) setFormPriority;
    SelectPriority(this.priority, this.setFormPriority, {Key? key})
    : super(key: key);
    @override
    State<SelectPriority> createState() => _SelectPriorityState();
    }
    class _SelectPriorityState extends State<SelectPriority> {
    @override
    Widget build(BuildContext context) {
    return Padding(
    padding: const EdgeInsets.only(top: 15),
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    const Text('Priority'),
    DropdownButtonFormField<int>(
    onChanged: ((int? value) {
    final valueOrDefault = value ?? PriorityLevel.low;
    widget.setFormPriority(valueOrDefault);
    setState(() {
    widget.priority = valueOrDefault;
    });
    }),
    value: widget.priority,
    items: [
    DropdownMenuItem(
    value: PriorityLevel.low, child: const Text("Low")),
    DropdownMenuItem(
    value: PriorityLevel.medium, child: const Text("Medium")),
    DropdownMenuItem(
    value: PriorityLevel.high, child: const Text("High")),
    DropdownMenuItem(
    value: PriorityLevel.severe, child: const Text("Severe")),
    ],
    ),
    ],
    ),
    );
    }
    }
  3. Ahora, añade el widget SelectPriority a los widgets CreateItem y ModifyItem. También necesitas añadir lógica adicional para gestionar la configuración de la prioridad. El código que debes añadir se muestra a continuación.

    Algunas secciones de los archivos que estás agregando se reemplazan con comentarios en los siguientes ejemplos de código para enfocarse en las secciones de código relevantes que se modifican.

    Edita el widget CreateItemForm en lib/components/create_item.dart:

    lib/componentes/create_item.dart
    // ... other imports
    import 'package:flutter_todo/components/select_priority.dart';
    // ... CreateItemAction widget
    class CreateItemForm extends StatefulWidget {
    const CreateItemForm({Key? key}) : super(key: key);
    @override
    createState() => _CreateItemFormState();
    }
    class _CreateItemFormState extends State<CreateItemForm> {
    final _formKey = GlobalKey<FormState>();
    late TextEditingController _itemEditingController;
    int _priority = PriorityLevel.low;
    void _setPriority(int priority) {
    setState(() {
    _priority = priority;
    });
    }
    // ... initState() and dispose() @override functions
    @override
    Widget build(BuildContext context) {
    TextTheme theme = Theme.of(context).textTheme;
    return formLayout(
    context,
    Form(
    key: _formKey,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    // ... Text and TextFormField widgets
    SelectPriority(_priority, _setPriority),
    // ... Padding widget
    ],
    ),
    ));
    }
    void save(RealmServices realmServices, BuildContext context) {
    if (_formKey.currentState!.validate()) {
    final summary = _itemEditingController.text;
    realmServices.createItem(summary, false, _priority);
    Navigator.pop(context);
    }
    }
    }

    Edita el widget ModifyItemForm en lib/components/modify_item.dart:

    lib/components/modify_item.dart
    // ... other imports
    import 'package:flutter_todo/components/select_priority.dart';
    class ModifyItemForm extends StatefulWidget {
    final Item item;
    const ModifyItemForm(this.item, {Key? key}) : super(key: key);
    @override
    _ModifyItemFormState createState() => _ModifyItemFormState(item);
    }
    class _ModifyItemFormState extends State<ModifyItemForm> {
    final _formKey = GlobalKey<FormState>();
    final Item item;
    late TextEditingController _summaryController;
    late ValueNotifier<bool> _isCompleteController;
    late int? _priority;
    void _setPriority(int priority) {
    setState(() {
    _priority = priority;
    });
    }
    _ModifyItemFormState(this.item);
    @override
    void initState() {
    _summaryController = TextEditingController(text: item.summary);
    _isCompleteController = ValueNotifier<bool>(item.isComplete)
    ..addListener(() => setState(() {}));
    _priority = widget.item.priority;
    super.initState();
    }
    @override
    void dispose() {
    _summaryController.dispose();
    _isCompleteController.dispose();
    super.dispose();
    }
    @override
    Widget build(BuildContext context) {
    TextTheme myTextTheme = Theme.of(context).textTheme;
    final realmServices = Provider.of<RealmServices>(context, listen: false);
    return formLayout(
    context,
    Form(
    key: _formKey,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    // ... Text and TextFormField widgets
    SelectPriority(_priority ?? PriorityLevel.medium, _setPriority),
    // ... StatefulBuilder widget
    Padding(
    padding: const EdgeInsets.only(top: 15),
    child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
    cancelButton(context),
    deleteButton(context,
    onPressed: () =>
    delete(realmServices, item, context)),
    okButton(context, "Update",
    onPressed: () async => await update(
    context,
    realmServices,
    item,
    _summaryController.text,
    _isCompleteController.value,
    _priority)),
    ],
    ),
    ),
    ],
    )));
    }
    Future<void> update(BuildContext context, RealmServices realmServices,
    Item item, String summary, bool isComplete, int? priority) async {
    if (_formKey.currentState!.validate()) {
    await realmServices.updateItem(item,
    summary: summary, isComplete: isComplete, priority: priority);
    Navigator.pop(context);
    }
    }
    void delete(RealmServices realmServices, Item item, BuildContext context) {
    realmServices.deleteItem(item);
    Navigator.pop(context);
    }
    }
  4. Ahora añade un indicador visual de prioridad en el widget ItemCard en lib/components/todo_item.dart. Crea un nuevo widget _PriorityIndicator que brinde un indicador visual de la prioridad del ítem.

    Añade un widget _PriorityIndicator que acabas de crear al widget TodoItem.

    lib/components/todo_item.dart
    // ... imports
    enum MenuOption { edit, delete }
    class TodoItem extends StatelessWidget {
    final Item item;
    const TodoItem(this.item, {Key? key}) : super(key: key);
    @override
    Widget build(BuildContext context) {
    final realmServices = Provider.of<RealmServices>(context);
    bool isMine = (item.ownerId == realmServices.currentUser?.id);
    return item.isValid
    ? ListTile(
    // ... leading property and child content
    title: Row(
    children: [
    Padding(
    padding: const EdgeInsets.only(right: 8.0),
    child: _PriorityIndicator(item.priority),
    ),
    SizedBox(width: 175, child: Text(item.summary)),
    ],
    ),
    // ... subtitle, trailing, and shape properties with child content
    )
    : Container();
    }
    // ... handleMenuClick() function
    }
    class _PriorityIndicator extends StatelessWidget {
    final int? priority;
    const _PriorityIndicator(this.priority, {Key? key}) : super(key: key);
    Widget getIconForPriority(int? priority) {
    if (priority == PriorityLevel.low) {
    return const Icon(Icons.keyboard_arrow_down, color: Colors.blue);
    } else if (priority == PriorityLevel.medium) {
    return const Icon(Icons.circle, color: Colors.grey);
    } else if (priority == PriorityLevel.high) {
    return const Icon(Icons.keyboard_arrow_up, color: Colors.orange);
    } else if (priority == PriorityLevel.severe) {
    return const Icon(
    Icons.block,
    color: Colors.red,
    );
    } else {
    return const SizedBox.shrink();
    }
    }
    @override
    Widget build(BuildContext context) {
    return getIconForPriority(priority);
    }
    }
3

Antes de volver a ejecutar la aplicación, realice un reinicio en caliente. Esto garantiza que la sesión de sincronización se reinicie con el nuevo esquema y evita errores de sincronización.

Luego, Iniciar sesión usando la cuenta que creaste anteriormente en este tutorial. Verás el único elemento que creaste anteriormente. Agrega un nuevo elemento, y verás que ahora puedes establecer la prioridad. Elija High para la prioridad y guarde el elemento.

Ahora vuelve a la página de datos de Atlas en tu navegador y actualiza la colección Item. Ahora deberías ver el nuevo ítem con el campo priority añadido y configurado en 1. También notarás que el Item existente ahora también tiene un campo priority, y está configurado en null, como se muestra en la siguiente captura de pantalla:

Dos artículos en una colección
haga clic para ampliar

Nota

¿Por qué no se rompió esta sincronizar?

Adding a property to a Realm object is not a breaking change and therefore does not require a client reset. The template app has Development Mode enabled, so changes to the client Realm object are reflected in the server-side schema. For more information, see Development Mode and Update Your Data Model.

Now that we added the priority field, we want to update the Device Sync subscription to only sync Items marked as a High or Severe priority.

1

En el archivo lib/realm/realm_services.dart, definimos la suscripción de Sincronización Flexible que define qué documentos sincronizamos con el dispositivo y la cuenta del usuario. Actualmente, sincronizamos todos los documentos cuya propiedad owner coincide con el usuario autenticado.

La suscripción actual:

lib/realm/realm_services.dart
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(r'owner_id == $0', [currentUser?.id]),
name: queryMyItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}

Now we're going to change the subscription to only sync High and Severe priority Items. As you may recall, the priority field is of type int, where the highest priority ("Severe") has a value of 0, and the lowest priority ("Low") has a value of 3.

We can make direct comparisons between an int and the priority property. To do so, we're going to refactor the subscription query to include Items where the priority is less than or equal to PriorityLevel.high (or 1). We will also give the subscription the new name "getMyHighPriorityItemsSubscription".

Actualiza la suscripción para borrar la suscripción antigua y crear una nueva que utilice prioridad:

lib/realm/realm_services.dart
// ... imports
class RealmServices with ChangeNotifier {
static const String queryAllName = "getAllItemsSubscription";
static const String queryMyItemsName = "getMyItemsSubscription";
static const String queryMyHighPriorityItemsName =
"getMyHighPriorityItemsSubscription";
bool showAll = false;
bool offlineModeOn = false;
bool isWaiting = false;
late Realm realm;
User? currentUser;
App app;
RealmServices(this.app) {
if (app.currentUser != null || currentUser != app.currentUser) {
currentUser ??= app.currentUser;
realm = Realm(Configuration.flexibleSync(currentUser!, [Item.schema]));
showAll = (realm.subscriptions.findByName(queryAllName) != null);
// Check if subscription previously exists on the realm
final subscriptionDoesNotExists =
(realm.subscriptions.findByName(queryMyHighPriorityItemsName) ==
null);
if (realm.subscriptions.isEmpty || subscriptionDoesNotExists) {
updateSubscriptions();
}
}
}
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(
r'owner_id == $0 AND priority <= $1',
[currentUser?.id, PriorityLevel.high],
),
name: queryMyHighPriorityItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}
// ... other methods
}
2

Vuelve a ejecutar la aplicación. Inicia sesión usando la cuenta que creaste anteriormente en este tutorial.

After an initial moment when Realm resyncs the document collection, you might see an error message resembling the following:

The following RangeError was thrown building StreamBuilder<RealmResultsChanges<Item>>(dirty, state:
_StreamBuilderBaseState<RealmResultsChanges<Item>, AsyncSnapshot<RealmResultsChanges<Item>>>#387c4):
RangeError (index): Invalid value: Only valid value is 0: 3

Este error puede ocurrir con el widget StreamBuilder a medida que la suscripción se actualiza. En una aplicación de producción, podrías agregar manejo de errores. Pero para el propósito de este tutorial, simplemente realiza una actualización en caliente y el error desaparecerá.

Ahora deberías ver el nuevo elemento de alta prioridad que creaste.

Tip

Cambiar suscripciones con el modo de desarrollador habilitado

In this tutorial, when you change the subscription and query on the priority field for the first time, the field is automatically added to the Device Sync Collection Queryable Fields. This occurs because the template app has Development Mode enabled by default. If Development Mode was not enabled, you would have to manually add the field as a queryable field to use it in a client-side Sync query.

Para obtener más información, consulte Campos consultables.

Si desea probar la funcionalidad con más detalle, puede crear elementos con diferentes prioridades. Verá que un nuevo elemento con una prioridad menor aparece brevemente en la lista de elementos y luego desaparece. Realm crea el elemento localmente, lo sincroniza con el backend y lo elimina porque no cumple con las reglas de suscripción. Esto se denomina escritura compensatoria.

También, notarás que el documento que creaste inicialmente no está sincronizado porque tiene una prioridad de null. Si quieres que este elemento se sincronice, puedes editar el documento en la Interfaz de Usuario de Atlas y agregar un valor para el campo de prioridad, o puedes cambiar tu suscripción para incluir documentos con valores nulos. También le daremos a la suscripción el nuevo nombre "getUserItemsWithHighOrNoPriority".

lib/realm/realm_services.dart
class RealmServices with ChangeNotifier {
static const String queryAllName = "getAllItemsSubscription";
static const String queryMyItemsName = "getMyItemsSubscription";
static const String queryMyHighPriorityItemsName =
"getMyHighPriorityItemsSubscription";
static const String queryMyHighOrNoPriorityItemsName =
"getMyHighOrNoPriorityItemsSubscription";
bool showAll = false;
bool offlineModeOn = false;
bool isWaiting = false;
late Realm realm;
User? currentUser;
App app;
RealmServices(this.app) {
if (app.currentUser != null || currentUser != app.currentUser) {
currentUser ??= app.currentUser;
realm = Realm(Configuration.flexibleSync(currentUser!, [Item.schema]));
// Check if subscription previously exists on the realm
final subscriptionDoesNotExists =
realm.subscriptions.findByName(queryMyHighOrNoPriorityItemsName) ==
null;
if (realm.subscriptions.isEmpty || subscriptionDoesNotExists) {
updateSubscriptions();
}
}
}
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
if (showAll) {
mutableSubscriptions.add(realm.all<Item>(), name: queryAllName);
} else {
mutableSubscriptions.add(
realm.query<Item>(
r'owner_id == $0 AND priority IN {$1, $2, $3}',
[currentUser?.id, PriorityLevel.high, PriorityLevel.severe, null],
),
name: queryMyHighPriorityItemsName);
}
});
await realm.subscriptions.waitForSynchronization();
}
// ... other methods
}

Nuevamente, cuando se produce un error StreamBuilder la primera vez que abres la aplicación con la nueva suscripción, realiza una actualización rápida para ver los datos esperados.

Agregar una propiedad a un objeto Realm existente es un cambio no disruptivo, y el modo de desarrollo asegura que el cambio de esquema se refleje en el servidor.

Nota

Share Feedback

¿Cómo te fue? Usa el Rate this page widget en la parte inferior derecha de la página para evaluar su efectividad. O reporta un problema en el repositorio de GitHub si tuviste algún problema.

Next

¿Qué son los servicios de aplicación Atlas?