Поиск Просмотр с комнатой - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь найти способ получить данные из Room при поиске в строке поиска. В моей базе данных 200000 строк данных.

Я нашел относительную статью http://www.zoftino.com/android-search-functionality-using-searchview-and-room,, но это неправильно. Он регистрирует наблюдателя каждый раз, когда изменяется текст. Есть ли другой способ?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Почему бы не попробовать запросы по частям, чтобы переполнение 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>>
}

Если возвращаемые данные также огромны, то я рекомендую вам взглянуть на PagingLibrary с android https://developer.android.com/topic/libraries/architecture/paging/ и интегрировать его в комнату. Это поможет вам отобразить результаты, которые вы, по сути, отобразите в пользовательском интерфейсе.

Наконец, у вас может быть рекурсивный вызов с окном индекса

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> 2 МБ. Надеюсь, это поможет

Примечание : В этом примере используется Rx Java2, поэтому подписка вызывает

0 голосов
/ 04 июля 2018

Не рекомендуется использовать такую ​​большую базу данных на 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 вы можете запросить базу данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...