2017-02-08 10 views
1

私はthe sampleを使用しています。私の要件に合わせてコードを修正しました。私はRxを学んでいて、それがどのように動作するかに完全に精通していません。だから、私のフラグメントに私がRxAndroidを使用してデータベース項目をフィルタリングする適切な方法

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がこれを効率的にするためのデバウンス演算子を提供していると信じていますが、このサブスクリプションコードをどのように組み合わせてtextViewの変更を聴取し、そのテキストに従ってフィルターをかけることができないのか分かりません。

私はすでに"SELECT * FROM " + TodoItem.TABLE + " WHERE " + TodoItem.DESCRIPTION + " LIKE \"" + query + "\" LIMIT 5”;

にLIST_QUERYを変更しようとしたし、次に試した中:

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追加された新しいタイプされたと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を購読しなければならないと思っていますが、既存のデータベース購読コードと組み合わせてください。ソリューションをお探しですか?

答えて

3

これを行う方法はいくつかあります。あなたは、フィルタは、Javaに存在する場合、あなたはQueryObservableasRows演算子を使用することができます。

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文字以上の任意の文字と一致します。 _ワイルドカードは1文字に一致します。

他の部分は、リストが正しく更新されていないことです。あなたはここで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文字列を合成するだけです。

+0

私は自分で%を把握することができましたが、残りは非常に役に立ちました。どうもありがとうございました。 –

関連する問題