gpt4 book ai didi

android - Realm 查询更新未反射(reflect)在 RealmRecyclerViewAdapter 中

转载 作者:搜寻专家 更新时间:2023-11-01 09:32:38 25 4
gpt4 key购买 nike

一直在使用 realm,它很棒。

遇到了一些事情。想知道我是否做错了什么。

我有一个 RealmRecyclerViewAdapter 用来显示 Realm 查询的结果。如果我在 Realm 中添加或更新记录,这将非常有效。我必须在回收器 View 上 setHasFixedSize(false) 以使其即时更新。不确定这是否正确,但它有效。

无论如何,这不是我的问题。

我正在尝试过滤我的数据。我有以下查询:

realm.where(Person::class.java).contains("name", nameFilter, Case.INSENSITIVE).findAllSorted("name")

我将这个 RealmResults 传递给我的回收站 View ,它在添加/更新时效果很好。

但是,当我尝试过滤器时,它不会自动更新。

我说的对吗?仅更改过滤器(由 nameFilter 指定)不足以重新运行查询?我想这很公平。因为我想没有触发器让 Realm 知道我已经更改了字符串的值。

但是,即使我重新计算我的查询,它似乎也不会在 Recycler View 中更新,除非我在我的适配器上显式调用 updateData。我不确定这是否是最好或最有效的方法。有没有更好的办法?

完整代码:

主要 Activity

class MainActivity : AppCompatActivity(), View.OnClickListener {

private val TAG: String = this::class.java.simpleName

private val realm: Realm = Realm.getInstance(RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build())

private var nameFilter = ""

private var allPersons: RealmResults<Person> = realm.where(Person::class.java).contains("name", nameFilter, Case.INSENSITIVE).findAllSorted("name")

private val adapter: PersonRecyclerViewAdapter = PersonRecyclerViewAdapter(allPersons)

private lateinit var disposable: Disposable

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

realm.executeTransaction({
// realm.deleteAll()
})

Log.i(TAG, "Deleted all objects from Realm")

buttonAddOrUpdatePerson.setOnClickListener(this)

setUpRecyclerView()

disposable = RxTextView.textChangeEvents(editTextNameFilter)
// .debounce(400, TimeUnit.MILLISECONDS) // default Scheduler is Computation
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith<DisposableObserver<TextViewTextChangeEvent>>(getSearchObserver())

}

private fun getSearchObserver(): DisposableObserver<TextViewTextChangeEvent> {
return object : DisposableObserver<TextViewTextChangeEvent>() {
override fun onComplete() {
Log.i(TAG,"--------- onComplete")
}

override fun onError(e: Throwable) {
Log.i(TAG, "--------- Woops on error!")
}

override fun onNext(onTextChangeEvent: TextViewTextChangeEvent) {
nameFilter = editTextNameFilter.text.toString()

allPersons = realm.where(Person::class.java).contains("name", nameFilter, Case.INSENSITIVE).findAllSorted("name")

// this is necessary or the recycler view doesn't update
adapter.updateData(allPersons)

Log.d(TAG, "Filter: $nameFilter")
}
}
}

override fun onDestroy() {
super.onDestroy()

realm.close()
}

override fun onClick(view: View?) {
if(view == null) return

when(view) {
buttonAddOrUpdatePerson -> handleAddOrUpdatePerson()
}
}

private fun handleAddOrUpdatePerson() {
val personToAdd = Person()
personToAdd.name = editTextName.text.toString()
personToAdd.email = editTextEmail.text.toString()

realm.executeTransactionAsync({
bgRealm -> bgRealm.copyToRealmOrUpdate(personToAdd)
})
}

private fun setUpRecyclerView() {
recyclerViewPersons.layoutManager = LinearLayoutManager(this)
recyclerViewPersons.adapter = adapter
recyclerViewPersons.setHasFixedSize(false)
recyclerViewPersons.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
}
}

PersonRecyclerViewAdapter

internal class PersonRecyclerViewAdapter(data: OrderedRealmCollection<Person>?, autoUpdate: Boolean = true) : RealmRecyclerViewAdapter<Person, PersonRecyclerViewAdapter.PersonViewHolder>(data, autoUpdate) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.person_row, parent, false)

return PersonViewHolder(itemView)
}

override fun onBindViewHolder(holder: PersonViewHolder?, position: Int) {
if(holder == null || data == null) return

val personList = data ?: return

val person = personList[position]

holder.bind(person)
}

internal class PersonViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var textViewName: TextView = view.findViewById(R.id.textViewNameDisplay)
var textViewEmail: TextView = view.findViewById(R.id.textViewEmailDisplay)

internal fun bind(person: Person) {
textViewEmail.text = person.email
textViewName.text = person.name
}
}
}

最佳答案

是的,updateData() 是实现它的方法。由于您更新了查询,因此您要显示的 Results 变成了不同的对象。必须调用 updateData() 来通知适配器数据源已更改。

但是,这样你可能会失去 RecyclerView 的漂亮动画,因为整个 View 会因为数据源的改变而被刷新。有一些方法可以解决这个问题。

例如:您可以将一个字段isSelected 添加到Person。通过isSelected字段查询结果并传递给适配器:

allPersons = realm.where(Person::class.java).equalTo("isSelected", true).findAllSorted("name")
adapter = PersonRecyclerViewAdapter(allPersons)

更改查询时:

realm.executeTransactionAsync({
var allPersons = realm.where(Person::class.java).equalTo("isSelected", true).findAllSorted("name")
for (person in allPersons) person.isSelected = false; // Clear the list first
allPersons = realm.where(Person::class.java).contains("name", nameFilter, Case.INSENSITIVE).findAllSorted("name") // new query
for (person in allPersons) person.isSelected = true;
})

这取决于你的用例,如果要显示的列表很长,这种方法可能会很慢,你可以尝试将所有过滤的人添加到 RealmList 并设置 RealmList 作为适配器的数据源。 RealmList.clear() 是一种比迭代整个结果集以设置 isSelected 字段更快的操作。

如果过滤器主要导致整个 View 被刷新,updateData() 就足够了,然后就使用它吧。

关于android - Realm 查询更新未反射(reflect)在 RealmRecyclerViewAdapter 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45803103/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com