搜索房间视图

时间:2018-07-04 05:01:10

标签: android android-room

在搜索栏上搜索时,我试图找到一种从Room获取数据的方法。我的数据库有20万行数据。

我找到了相关的文章http://www.zoftino.com/android-search-functionality-using-searchview-and-room,但这是错误的。每次文本更改时,他都会注册一名观察员。还有另一种方法吗?

2 个答案:

答案 0 :(得分:1)

不建议在onQueryTextChange上访问如此大的数据库,但如果愿意,仍然可以使用TimerTask来减少对数据库的访问次数

    Timer timer;
    long delay = 2000;  //user input delay

    private void cancelAndReschedule() {
        if (timer != null) {
            timer.cancel();
        }

        timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {

                //query database

                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {

                        //update ui
                    }
                });
            }
        };
        timer.schedule(task, delay);
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        cancelAndReschedule();
        return true;
    }

另一种方法是将AutoCompleteTextView与预先加载的建议列表一起使用,并在itemclick上可以查询数据库

答案 1 :(得分:1)

为什么不尝试分块查询,以免发生CursorWindowSize溢出。您可以为

配置DAO
interface MyDbObjectDao {
    @Query("SELECT * FROM myTable WHERE mySearchName LIKE :value LIMIT :startIndex, :endIndex")
    fun mySearchQueryBetween(value: String, startIndex: Int, endIndex: Int): Single<List<MySearchData>>

    @Query("SELECT * FROM myTable WHERE mySearchName LIKE :value LIMIT :tillIndex")
    fun mySearchQueryStart(value: String, tillIndex: Int): Single<List<MySearchData>>
}

如果返回的数据也很大,那么建议您查看一下Android https://developer.android.com/topic/libraries/architecture/paging/上的PagingLibrary并将其集成到房间中。这将帮助您分页基本上将在UI上显示的结果。

最后,您可以使用索引窗口进行递归调用

class MyRepository(val myDao: MyDbObjectDao) {
    private val searchProcessor = BehaviorProcessor.create<List<SearchData>>()
    private var searchIndex = 1

    fun queryMySearch(value: String) : Flowable<List<SearchData>> {
        startSearch(value)
        return searchProcessor.hide()
    }

    private fun startSearch(value: String) {
        if (searchIndex * searchableWindow) >= myDao.totalRowCount()) {
            searchProcessor.onComplete()
            return
        }
        if (searchIndex = 1) {
            myDao.mySearchQueryStart(value, searchableWindow)
                 .subscribeOn(Schedulers.io())
                 .subscribe({ onSearchCall(value, it) }, { searchProcessor.onError(it) })
        } else {
             myDao.mySearchQueryBetween(value, searchableWindow.startIndex, searchableWindow.endIndex)
                .subscribeOn(Schedulers.io())
                .subscribe({ onSearchCall(value, it) }, { searchProcessor.onError(it) })
        }

    }

    private fun onSearchCall(value: String, list: List<MySearchData>) {
        if (list.isNotEmpty()){
            searchProcessor.onNext(list.map { it.toSearchData() })
        }
        searchIndex++
        startSearch(value)
    }

    private val Int.startIndex : Int
         get() = this * (searchIndex -1)

    private val Int.endIndex : Int
         get() = this * searchIndex

    companion object {
        private const val searchableWindow = 200
    }
}

您认为可以

class MySearchFragment : BaseFragment(), SearchView.OnQueryTextListener {
    override fun onQueryTextChange(String newText) {
         viewModel.queryMySearchToRepo(newText)
              .observeOn(AndroidSchedulers.mainThread)
              .subscribe(this@MySearchFragment::adaptList, { it.printStackTrace() }, {
                  recyclerView?.hideLoadingProgress() 
              })
         return true;
    }

    private fun adaptList(list: List<SearchData>) {
        // set or add data to the adapter accordingly
        // with notifyRangeInserted(adapterList.size -1, list.size)
    }
}

所有操作都是具有同步递归的异步操作,因此数据库查询不会太频繁,并且您也不会遇到CursorWindow溢出> 2mb。希望这会有所帮助

注意此示例使用Rx Java2,因此订阅调用