#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.