在搜索栏上搜索时,我试图找到一种从Room
获取数据的方法。我的数据库有20万行数据。
我找到了相关的文章http://www.zoftino.com/android-search-functionality-using-searchview-and-room,但这是错误的。每次文本更改时,他都会注册一名观察员。还有另一种方法吗?
答案 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
溢出。您可以为
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,因此订阅调用