Царство, возвращающее устаревшие данные

У меня нет большого опыта написания приложений для Android. Для удовольствия я пишу приложение, которое будет загружать мои журналы вызовов на мой сервер. Все это приложение работает как служба. Служба (запускается при загрузке телефона) является той, которая регистрирует ContentObserver, который затем вызывает мой собственный класс CallLog . Я использую ContentObserver для прослушивания событий изменения контента. К сожалению, ContentObserver вызывается несколько раз, когда я набираю номер.

По этой причине у меня есть функция, которую я вызываю после успешной загрузки (я использую Retrofit), называемый markAsUploaded() . Эта функция создает объект RealmObject называемый CallLogUploaded (который отличается от моей обычной модели CallLog ). Этот CallLogUploaded просто имеет один идентификатор, который является dateTime вызова, который должен быть достаточно уникальным. Затем, когда я повторяю список всех журналов вызовов, я проверяю каждый журнал вызовов на функцию isDataUploaded() , которая выполняет запрос Realm, и проверяет, существует ли уже журнал вызовов с этой датой, хранящейся в база данных (область). Теоретически он должен работать.

Однако я заметил, что это не всегда работает. Похоже, что очень часто мои данные устарели. Когда я выполняю realm.isAutoRefresh() , он возвращает false (хотя я клянусь, что он вернул true однажды). В моей функции isDataUploaded , даже когда я isDataUploaded findAll() в Realm, я не вижу всех своих данных, но данные определенно попали в функцию markDataAsUploaded .

Вот мой код – это в Котлине, но его должно быть легко понять:

  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 } 

Я очень новичок в Realm и довольно новичок в разработке Android, поэтому я был бы признателен за любую помощь, которую вы можете мне дать. Благодаря!

Это потому что

 // 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() } } 

У этого метода есть довольно много ошибок, о которых я писал давно

  • Экземпляр Realm открывается, но никогда не закрывается

  • Для каждого элемента есть новая транзакция, а не вставка всех элементов в одну транзакцию

Если вы не закрываете экземпляр Realm (каждый экземпляр требует своего собственного вызова close() ), то ваш экземпляр Realm никогда не будет обновляться, если вы фактически не начнете транзакцию и не выполните транзакции внутри транзакции.

У вас есть три решения:

1.) сделайте свою логику в фоновом потоке внутри транзакции, если ничего не сделать, отмените транзакцию – запросы, сделанные в транзакциях, никогда не затухают

2.) убедитесь, что экземпляр Realm закрыт должным образом (хотя это определенно необходимость в любом неавтоматизирующем потоке)

3.) хакерским решением является вызов RealmRefresh.refreshRealm() после getDefaultInstance() соответствии с моим ответом на Stack Overflow, который опирается на API-интерфейс пакета, но он работает для решения этой проблемы


Обычно вам нужно открыть экземпляр Realm в начале потока и закрыть его в конце потока.

так что это в основном одна большая try(Realm realm = Realm.getDefaultInstance() { ... } для onHandleIntent() .


enqueue(new Callback() { @Override public void onSuccess(..) {...} работает в потоке пользовательского интерфейса. Чтобы запустить его в текущем потоке, вы должны использовать call.execute() .


вместо

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

делать

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

Чтобы узнать о сохранении версии, вы можете прочитать https://medium.com/@Zhuinden/understanding-realm-version-retention-and-synchronization-9a513c2445bb .

Intereting Posts
Kotlin создает проблемы с Android Можно ли выразить kotlin 'с' эквивалентом метода в Scala? Android, Gradle, Realm, Kotlin: Ошибка: ошибка: не удалось найти файл AndroidManifest.xml Listview: плавный свиток вниз Kotlin 'rem' в качестве замены для «мода» недоступен? kotlin retrofit-Background sticky concurrent mark sweep GC освобожден 65326 (1448KB) Объекты AllocSpace, 62 (1736KB) Объекты LOS, Почему инициализаторы свойств не вызывают пользовательский сеттер? Kotlin – Это отличный способ бросить NotImplementedError для всех методов класса? Класс данных Kotlin: почему toString () экспортирует закрытые свойства Почему Spring-data-elasticsearch не использует объект-образец из весеннего контекста Как отфильтровать список на месте с Kotlin? Как использовать Kotlin coroutines wait () в главной теме Создание нового проекта в Android studio-Kotlin kotlin-андроид-расширения в ViewHolder Класс Kotlin Custom View реализует интерфейс, который не может быть разрешен в `: app: compileDebugKotlinAfterJava`. Идентичная версия Java отлично работает