簡體   English   中英

使用RxAndroid過濾數據庫項的正確方法

[英]Proper way to filter database items using RxAndroid

我正在使用提供的示例 ,並根據我的要求調整了代碼。 我正在學習Rx,並不完全熟悉它是如何工作的。 所以,在我的片段中,我有

private static String LIST_QUERY = "SELECT * FROM " + TodoItem.TABLE;

我的onResume看起來像:

@Override
public void onResume() {
    super.onResume();

    subscription = db.createQuery(TodoItem.TABLE, LIST_QUERY)
            .mapToList(TodoItem.MAPPER)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(adapter);
}

適配器在列表視圖中顯示數據並且它工作正常,但現在我在列表頂部添加了一個TextView,並希望在用戶輸入文本時過濾結果。 我相信RxAndroid提供了一個debounce運算符來提高效率(而不是立即查詢數據庫),但我不確定如何結合此訂閱代碼來收聽textView更改並根據該文本進行過濾。

我已經嘗試將LIST_QUERY更改為"SELECT * FROM " + TodoItem.TABLE + " WHERE " + TodoItem.DESCRIPTION + " LIKE \\"" + query + "\\" LIMIT 5”;

然后嘗試:

    etSearch.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence searchQuery, int i, int i1, int i2) {
            query = searchQuery.toString();
            adapter.notifyDataSetChanged();
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { //ignore }

        @Override
        public void afterTextChanged(Editable editable) { //ignore }
    });

這導致列表為空(我認為這是好的,因為初始查詢是空字符串)但是當我輸入一些文本時,查詢根本沒有更新/過濾列表。

我嘗試了另一種方法,並在mapToList之后添加了take(5)(因為我想要LIMIT 5),並且只顯示了5個項目。 然后我添加了.filter(,鍵入new並讓Android Studio生成Func1代碼,它看起來像:

    subscription = db.createQuery(ListItem.TABLE, LIST_QUERY)
            .mapToList(Item.MAPPER)
            .filter(new Func1<List<ListItem>, Boolean>() {
                @Override
                public Boolean call(List<ListItem> items) {
                    return null;
                }
            })

所以問題是它要求我過濾整個列表。 我試過這個:

public Boolean call(List<ListItem> items) {
   for(ListItem i: items)
      if(!i.description().startsWith(query))
          items.remove(i);
   return true;
}

但仍然顯示整個列表,並且文本中的更改不會使列表發生變化。 我相信我錯過了一些東西,我必須訂閱EditText,但我不知道如何做到這一點並將它與現有的數據庫訂閱代碼結合起來。 尋找解決方案。

有幾種不同的方法可以做到這一點。 如果你想過濾器在Java中存在,那么你可以使用asRows運營商QueryObservable

database.createQuery(ListItem.TABLE, ListItem.QUERY)
  .flatMap(query -> query.asRows(Item.MAPPER)
    .filter(item -> item.description.startsWith(query))
    .toList())

這將是一個Observable<List<Item>> ,只包含與查詢匹配的項目。

但是,您的原始方法是理想的方法,您只是錯誤地使用LIKE 您可能希望包含通配符( %_ )以包含與查詢不完全匹配的結果。 例如:

"SELECT * FROM " + TodoItem.TABLE + " WHERE " + TodoItem.DESCRIPTION + " LIKE \"%" + query + "%\" LIMIT 5”;

將匹配描述中包含查詢的任何結果。 %通配符匹配任何字符的0或更多。 _通配符匹配單個字符。

您提到的另一部分是列表未正確更新。 你想在這里使用RxAndroid而不是textChangedListeners。 在你看來,你會有類似的東西

RxTextView.textChanges(editText)
  .switchMap(query -> database.createQuery(ListItem.TABLE, ListItem.query(query))
    .mapToList(ListItem.MAPPER))
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(list -> {
    adapter.setData(list);
    adapter.notifyDataSetChanged();
  });

這樣,您就不必擔心執行查詢和獲取通知調用的適配器之間的任何競爭。 ListItem.query(query)方法只是用查詢編寫sqlite字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM