首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >领域查询更新没有反映在RealmRecyclerViewAdapter中

问领域查询更新没有反映在RealmRecyclerViewAdapter中
EN

Stack Overflow用户
提问于 2017-08-21 17:58:16
回答 1查看 745关注 0票数 2

一直在使用领域而且很棒。

遇到了什么。不知道我是不是做错了什么。

我有一个RealmRecyclerViewAdapter,用于显示领域查询的结果。如果我在领域中添加或更新记录,这将非常有效。我不得不在setHasFixedSize(false)的回收视图,以使它的更新,在飞行。不确定这是否正确,但成功了。

不管怎样,这不是我的问题。

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

代码语言:javascript
复制
realm.where(Person::class.java).contains("name", nameFilter, Case.INSENSITIVE).findAllSorted("name")

我将这个RealmResults传递给我的回收商视图,它在添加/更新方面非常有用。

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

我是否正确地说,仅仅更改我的过滤器(由nameFilter指定)不足以重新运行查询?我想这是很公平的。因为我想领域没有触发器可以知道我已经更改了字符串的值。

但是,即使我重新计算了我的查询,除非我在适配器上显式地调用updateData,否则它似乎不会在回收器视图中更新。我不确定这是最好的还是最有效的方法。有更好的办法吗?

完整代码:

主活性

代码语言:javascript
复制
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

代码语言:javascript
复制
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
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2017-08-22 03:38:15

是啊,updateData()就是这么做的。因为您更新了查询,所以要显示的Results变成了一个不同的对象。必须调用updateData()通知适配器数据源已更改。

但是,您可能会以这种方式丢失RecyclerView的优秀动画,因为由于数据源发生了更改,整个视图将被刷新。有一些方法可以解决这个问题。

例:你可以在Person中添加一个字段Person。通过isSelected字段查询结果并将其传递给适配器:

代码语言:javascript
复制
allPersons = realm.where(Person::class.java).equalTo("isSelected", true).findAllSorted("name")
adapter = PersonRecyclerViewAdapter(allPersons)

更改查询时:

代码语言:javascript
复制
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字段更快。

如果过滤器主要会导致整个视图刷新,那么updateData()就足够好了,那么就使用它吧。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45803103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档