Docs Menu
Docs Home
/ /
SDK de dispositivos Atlas

Inicio Rápido con LiveData - Java SDK

Esta página contiene instrucciones para integrar rápidamente Realm en una aplicación de Android de ejemplo que utiliza Datos en vivoEsta aplicación de ejemplo permite a un usuario incrementar un contador usando un botón.

Esta guía de inicio rápido utiliza Sync para sincronizar los cambios de datos entre clientes. Antes de comenzar, asegúrese de tener:

Nota

Uso de LiveData sin sincronización

Para usar esta guía de inicio rápido sin sincronización, deshabilite las funciones de sincronización en el SDK. Puede hacerlo eliminando las siguientes líneas del archivo build.gradle de la aplicación:

realm {
syncEnabled = true
}

Después de eliminar las líneas, vuelva a sincronizar la configuración de Gradle para volver a cargar el SDK de Java en modo sin conexión. Elimine las líneas relacionadas con la importación y el uso de la configuración de sincronización, el inicio de sesión de usuario y los valores de partición de CounterModel archivo para utilizar el SDK de Java sin sincronización.

Para comenzar, copie el repositorio de ejemplo en su entorno local.

Ya hemos creado una aplicación para Android con la mayor parte del código necesario. Puedes clonar el repositorio de la aplicación cliente directamente desde GitHub:

git clone https://github.com/mongodb-university/realm-android-livedata.git

El repositorio contiene dos ramas: final y start. La rama final es una versión terminada de la aplicación como debe verse después de que completes este tutorial. Para seguir este tutorial, por favor revisa la rama start:

git checkout start

Ahora que has clonado el repositorio, necesitas agregar las dependencias necesarias para ejecutar el SDK de Java y Android LiveData. Comienza agregando la dependencia del SDK de Java al bloque buildscript.dependencies del archivo build.gradle de tu proyecto:

buildscript {
ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.realm:realm-gradle-plugin:10.2.0"
}
}

También tendrás que agregar la dependencia Android LiveData al bloque dependencies de tu archivo de nivel de aplicación build.gradle:

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

A continuación, habilite la sincronización en el SDK creando el siguiente bloque de nivel superior en el archivo de nivel de aplicación build.gradle:

realm {
syncEnabled = true
}

Luego, habilite DataBinding creando el siguiente bloque en el bloque android de su archivo de nivel de aplicación build.gradle:

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.mongodb.realm.livedataquickstart"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
dataBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

Por último, haga clic en el botón "Sincronizar" o seleccione Build > Rebuild Project en el menú de la aplicación para reconfigurar su configuración de Gradle con estos cambios y obtener las dependencias.

Con todas las dependencias en su lugar, es hora de crear una interfaz compatible con LiveData para nuestros objetos Realm. Para hacerlo, deberemos gestionar algunos eventos:

  • El método onActive() permite que un observador se suscriba a los cambios en el objeto Realm subyacente agregando un detector de cambios.

    override fun onActive() {
    super.onActive()
    val obj = value
    if (obj != null && RealmObject.isValid(obj)) {
    RealmObject.addChangeListener(obj, listener)
    }
    }
  • El método onInactive() permite que un observador cancele la suscripción a los cambios en el objeto Realm subyacente eliminando el detector de cambios.

    override fun onInactive() {
    super.onInactive()
    val obj = value
    if (obj != null && RealmObject.isValid(obj)) {
    RealmObject.removeChangeListener(obj, listener)
    }
    }
  • Cuando se produce un cambio, el miembro listener utiliza el método setValue() de la clase padre LiveData para pasar el valor del objeto Realm a la UI a menos que el objeto se haya eliminado, en cuyo caso el detector de cambios pasa un valor de null en lugar de pasar una referencia a un objeto eliminado no válido.

    private val listener =
    RealmObjectChangeListener<T> { obj, objectChangeSet ->
    if (!objectChangeSet!!.isDeleted) {
    setValue(obj)
    } else { // Because invalidated objects are unsafe to set in LiveData, pass null instead.
    setValue(null)
    }
    }

Tip

Uso de LiveData con RealmResults

Este ejemplo solo usa LiveData para mostrar RealmObjects en la interfaz de usuario. Para ver un ejemplo de implementación que RealmResults muestra, consulte LiveRealmResults.

Esta aplicación almacena toda su lógica y datos principales en un ViewModel llamado CounterModel. Al ejecutarse, crea una instancia de CounterModel que se utiliza hasta que se cierra. Esta instancia contiene los LiveData que se muestran en la interfaz de usuario de la aplicación. Para crear una instancia de LiveData, necesitamos acceder a un objeto Counter almacenado en un dominio y pasarlo al constructor LiveRealmObject. Para ello:

  1. Conéctese a su aplicación con su ID de aplicación.

  2. Autenticar un usuario.

  3. Conéctese a un reino específico mediante Sincronización.

  4. Consulta el reino en busca de un Counter, insertando un nuevo Counter si aún no se ha creado uno en este reino.

  5. Cree una instancia de LiveRealmObject utilizando la instancia Counter y almacénela en el miembro counter de CounterModel.

El siguiente fragmento de código implementa este comportamiento:

init {
val appID = "YOUR APP ID HERE" // TODO: replace this with your App ID
// 1. connect to the MongoDB Realm app backend
val app = App(
AppConfiguration.Builder(appID)
.build()
)
// 2. authenticate a user
app.loginAsync(Credentials.anonymous()) {
if(it.isSuccess) {
Log.v("QUICKSTART", "Successfully logged in anonymously.")
// 3. connect to a realm with Realm Sync
val user: User? = app.currentUser()
val partitionValue = "example partition"
val config = SyncConfiguration.Builder(user!!, partitionValue)
// because this application only reads/writes small amounts of data, it's OK to read/write from the UI thread
.allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true)
.build()
// open the realm
realm = Realm.getInstance(config)
// 4. Query the realm for a Counter, creating a new Counter if one doesn't already exist
// access all counters stored in this realm
val counterQuery = realm!!.where<Counter>()
val counters = counterQuery.findAll()
// if we haven't created the one counter for this app before (as on first launch), create it now
if (counters.size == 0) {
realm?.executeTransaction { transactionRealm ->
val counter = Counter()
transactionRealm.insert(counter)
}
}
// 5. Instantiate a LiveRealmObject using the Counter and store it in a member variable
// the counters query is life, so we can just grab the 0th index to get a guaranteed counter
this._counter.postValue(counters[0]!!)
} else {
Log.e("QUICKSTART", "Failed to log in anonymously. Error: ${it.error.message}")
}
}
}

Importante

No lea ni escriba en el hilo de UI

Las lecturas y escrituras en la base de datos son computacionalmente costosas, por lo que el SDK las deshabilita por defecto en el hilo de la interfaz de usuario. Para simplificar, este ejemplo habilita las lecturas y escrituras en el hilo de la interfaz de usuario con los métodos de configuración allowWritesOnUiThread() y allowQueriesOnUiThread(). En aplicaciones de producción, casi siempre se recomienda aplazar las lecturas y escrituras a un hilo en segundo plano mediante métodos asíncronos.

Para mostrar los datos almacenados en en la CounterModel interfaz de usuario de la aplicación, necesitamos acceder CounterModel al singleton mediante el método viewModels() cuando la aplicación CounterFragment crea. Una vez instanciado el modelo, podemos usar la biblioteca de enlace de datos de Android para mostrar los datos del modelo en los elementos de la interfaz de usuario.

Para acceder al singleton CounterModel cuando la aplicación crea CounterFragment, coloque el siguiente código en el método onCreateView() de CounterFragment:

val model: CounterModel by viewModels()

A continuación, configure los hooks de Data Binding en la UI para el fragmento del contador:

<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="counterModel"
type="com.mongodb.realm.livedataquickstart.model.CounterModel"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CounterFragment">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{counterModel.counter.value.get().toString()}"
android:textSize="58pt"
app:layout_constraintBottom_toTopOf="@id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Por último, conecte el modelo al enlace para que la interfaz de usuario pueda mostrar el contador e iterarlo al presionar el botón con el siguiente código en el método onCreateView() de CounterFragment:

val binding = CounterFragmentBinding.inflate(inflater, container, false).apply {
lifecycleOwner = viewLifecycleOwner
counterModel = model
}
binding.root.button.setOnClickListener {
Log.v("QUICKSTART", "Clicked increment button. Current value: ${model.counter.value?.value?.get()}")
model.incrementCounter()
}
return binding.root

Ahora debería poder ejecutar la aplicación de ejemplo. Verá una interfaz similar a esta:

La aplicación Contador de inicio rápido LiveData.

Al hacer clic en el botón "AÑADIR", el valor de tu contador se incrementará en uno. Con Sync, puedes consultar los registros de tu aplicación para ver eventos de incremento individuales. Android LiveData tiene en cuenta el ciclo de vida, por lo que girar la pantalla o liberar el estado de la aplicación borrando la RAM del dispositivo no debería afectar su estado, que debería reanudarse sin problemas y volver a suscribirse automáticamente a los eventos al reanudarse, utilizando el estado almacenado en el singleton del modelo y la instancia encapsulada de LiveData.

  • Utilice las clases LiveRealmObject y LiveRealmResults como plantilla para encapsular datos de Realm en vivo en Android LiveData.

  • Utilice un ViewModel para separar los datos subyacentes de los elementos de la interfaz de usuario que muestran esos datos.

  • DataBinding le permite declarar relaciones entre los datos del modelo y los elementos de la interfaz de usuario sin establecer valores explícitamente en una actividad o fragmento.

¿Te resultó útil esta guía de inicio rápido? ¡Comparte tu opinión con nosotros a través del formulario de comentarios a la derecha de la página!

Next

Bienvenido a la Docs de Atlas Device SDK

En esta página