Используйте RealmObject с адаптером списка Recyclerview

#android #android-recyclerview #realm

#Android #android-recyclerview #область

Вопрос:

Поскольку доступ к RealmObject возможен только в том потоке, в котором они были созданы, его невозможно использовать с ListAdapter из-за использования AsyncListDiffer, В этом случае вы получите это исключение

Доступ к области из неправильного потока. Доступ к объектам Realm возможен только в том потоке, в котором они были созданы.

Есть ли альтернатива? Моим первым предложением было бы отобразить RealmObject в Pojo, которые представляют данные просмотра, но поскольку в списке много изменений, это замедлит поток пользовательского интерфейса.

Комментарии:

1. зачем вам нужно использовать AsyncListDiffer?

2. Это повышает производительность, например, при обновлении элемента будет обновляться только соответствующий вид, а не все виды, отображаемые в recyclerview. В то же время это позволяет вам отслеживать элемент, который изменился

3. Смысл использования Realm в том, чтобы использовать его реактивность, поэтому вы можете использовать что-то вроде этого: github.com/realm/realm-android-adapters Он предупредит адаптер о том, что объекты были вставлены, удалены или обновлены, и обновит только измененные представления 😉

4. Правильно, используйте RealmRecyclerViewAdapter

5. Вы нашли способ? Единственный способ, который я нашел, — установить для основного потока значение AsyncDiffConfig. AsyncDifferConfig.Builder<Audio>(ITEM_CALLBACK) .setBackgroundThreadExecutor(Dispatchers.Main.asExecutor()) .build() . Интересно, есть ли решение получше.

Ответ №1:

Используйте Realm.copyFromRealm() available since 0.87.0 для создания копии уже сохраненного RealmObject.

Ответ №2:

Если в вашем DiffUtil.ItemCallback вы просто выполняете простое сравнение, после чего вы можете обернуть данные вашей области классом.

 class User: RealmObject {
   @PrimaryKey
   var uuid: String? = null
}
data class WrappedUserData(val uuid: Long, val user: User)

  

Затем используйте этот класс в качестве типа элемента адаптера

 class MyAdapter: ListAdapter<WrappedUserData, ItemViewHolder>
  

И используйте обернутый класс для сравнения.

 private val ITEM_CALLBACK = object : DiffUtil.ItemCallback<WrappedUserData>() {
    override fun areItemsTheSame(oldItem: WrappedUserData, newItem: WrappedUserData): Boolean {
        return oldItem.uuid == newItem.uuid
    }

    override fun areContentsTheSame(oldItem: WrappedUserData, newItem: WrappedUserData): Boolean {
        return oldItem.uuid == newItem.uuid
    }
}
  

При вызове myAdapter.submitList вам просто нужно сопоставить свои исходные данные со списком WrappedUser.

Комментарии:

1. Метод areContentsTheSame должен сравнивать содержимое двух элементов. В вашем примере, если изменяется свойство пользователя (например, имя пользователя), вы этого не увидите, потому что вы сравниваете только uuid.