Reino que devuelve datos obsoletos

No tengo mucha experiencia escribiendo aplicaciones de Android. Para divertirme, estoy escribiendo una aplicación que cargará mis loggings de llamadas a mi server. Toda esta aplicación se está ejecutando como un service. El Servicio (se inicia cuando se inicia el teléfono) es el que registra ContentObserver, que luego llama a mi class CallLog personalizada. Uso ContentObserver para escuchar events de cambio de contenido. Lamentablemente, ContentObserver se llama varias veces cuando, por ejemplo, marque un número.

Por esa razón, tengo una function a la que llamo después de una carga exitosa (utilizo Retrofit) llamada markAsUploaded() . Esta function crea un RealmObject llamado CallLogUploaded (que es diferente de mi model regular de CallLog ). Este CallLogUploaded simplemente tiene un identificador que es el dateTime de la llamada, que debe ser lo suficientemente único. Luego, cuando estoy iterando a través de la list de todos los loggings de llamadas, isDataUploaded() cada logging de llamadas con una function isDataUploaded() , que hace una consulta Realm y comtesting si ya hay un logging de llamadas con esa dateTime almacenada en el database (reino) En teoría debería funcionar.

Sin embargo, he notado que no siempre funciona. Parece que muy a menudo mis datos son obsoletos. Cuando hago realm.isAutoRefresh() , devuelve falso (aunque juro que volvió verdadero una vez). En mi function isDataUploaded , incluso cuando hago un findAll() en el Reino, no veo todos mis datos, pero definitivamente los datos golpean la function markDataAsUploaded .

Aquí está mi código: está en Kotlin, pero debería ser fácil de entender:

  val callLogCall = service.sendCalLLogs(childId, dataToUpload) callLogCall.enqueue(object : Callback<Void> { override fun onResponse(call: Call<Void>, response: Response<Void>) { if (response.isSuccessful) { Log.i(AppConstants.LOG_TAG, "Call log data uploaded successfully!") this@CallLogData.markDataAsUploaded(dataToUpload) } else { Log.w(AppConstants.LOG_TAG, "Call log data upload failed") } } override fun onFailure(call: Call<Void>, t: Throwable) { Log.w(AppConstants.LOG_TAG, "Call log data upload error (onFailure) called") } }) // This function simply stores a Realm model for all the data that has been uploaded to the server private fun markDataAsUploaded(dataToUpload: List<CallLog>) { realm = Realm.getDefaultInstance() for (data in dataToUpload) { realm.beginTransaction() val callLogUploaded = realm.createObject(CallLogUploaded::class.java) callLogUploaded.callDate = data.callDate realm.commitTransaction() } } // This function checks to see if the data is already uploaded. private fun isDataUploaded(callLog: CallLog) : Boolean { return realm .where(CallLogUploaded::class.java) .equalTo("callDate", callLog.callDate) .count() > 0L } // Gets the call logs - not the entire function for (call in callLogs) { val callLog = CallLog() callLog.id = call.id callLog.callDate = Utilities.getTimestampAsSeconds(call.callDate) if (this.isDataUploaded(callLog)) { continue } callLog.name = call.name callLog.number = call.number } 

Soy muy nuevo en Realm y bastante nuevo en el desarrollo de Android, por lo que agradecería cualquier ayuda que pueda brindarme. ¡Gracias!

Eso es porque

 // This function simply stores a Realm model for all the data that has been uploaded to the server private fun markDataAsUploaded(dataToUpload: List<CallLog>) { realm = Realm.getDefaultInstance() for (data in dataToUpload) { realm.beginTransaction() val callLogUploaded = realm.createObject(CallLogUploaded::class.java) callLogUploaded.callDate = data.callDate realm.commitTransaction() } } 

Este método tiene bastantes errores que escribí hace mucho time

  • La instancia de Realm se abre, pero nunca se cierra

  • Hay una nueva transacción por cada elemento, en lugar de insert todos los elementos en una sola transacción

Si no cierra la instancia de Realm (cada instancia requiere su propia llamada de close() ), su instancia de Realm nunca se actualizará a less que realmente comience una transacción y haga cosas dentro de la transacción.

Tienes tres soluciones:

1.) haga su lógica en el hilo de background dentro de una transacción, si no hay nada que hacer, luego cancele la transacción – las consultas realizadas en las transactions nunca son obsoletas

2.) asegúrate de que la instancia de Realm esté cerrada correctamente (aunque esto es definitivamente una necesidad en cualquier hilo no autoupdating)

3.) una solución hacky es llamar a RealmRefresh.refreshRealm() después de getDefaultInstance() acuerdo con mi respuesta en Stack Overflow que se basa en la API privada del package, pero funciona para resolver este problema.


Normalmente necesita abrir la instancia de Realm al principio del hilo y cerrarla al final del hilo.

por lo tanto, es básicamente una gran try(Realm realm = Realm.getDefaultInstance() { ... } para onHandleIntent() .


enqueue(new Callback() { @Override public void onSuccess(..) {...} ejecuta en la enqueue(new Callback() { @Override public void onSuccess(..) {...} de la interfaz de usuario. Para ejecutarla en la call.execute() actual, debe usar call.execute() .


en lugar de

 for (data in dataToUpload) { realm.beginTransaction() val callLogUploaded = realm.createObject(CallLogUploaded::class.java) callLogUploaded.callDate = data.callDate realm.commitTransaction() } 

hacer

 realm.beginTransaction() for (data in dataToUpload) { val callLogUploaded = realm.createObject(CallLogUploaded::class.java) callLogUploaded.callDate = data.callDate } realm.commitTransaction() 

Para comprender la retención de la versión, puede leer https://medium.com/@Zhuinden/understanding-realm-version-retention-and-synchronization-9a513c2445bb .

  • Cómo consultar Realm en el background Subprocess usando RxJava2
  • Cómo usar Realm en una biblioteca
  • La notificación de consulta de dominio no se activa con Kotlin
  • Float es un campo no válido para la comparación de Realm
  • Retrofit + Deserialization GSON + Relación de reino
  • Realm Android consulta una list de primitivos que no funcionan
  • CaptunetworkingTypeConstructor (*) no es un subtipo de RealmModel
  • Cómo arreglar "La característica no es parte del esquema para este Reino" en Kotlin Realm Extention
  • Basic Realm + Kotlin: RealmObject no está configurando valores pasados
  • No se puede configurar el Reino en el proyecto usando Kotlin
  • Función de extensión Kotlin: reference no resuelta