2017-02-08 1 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); 
} 

이 어댑터는 목록보기의 데이터를 보여주고 그것을 잘 작동하지만 지금은 상단에 텍스트 뷰를 추가 한 목록을 만들고 사용자가 텍스트를 입력 할 때마다 결과를 필터링하려고합니다. 나는 RxAndroid가 이것을 효율적으로 (그리고 DB를 즉시 쿼리하지 않기 위해) debounce 연산자를 제공한다고 믿지만이 구독 코드를 결합하여 textView 변경 사항을 듣고 텍스트에 따라 필터링 할 수 있는지 확신 할 수 없다.

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 } 
    }); 

이것은하지만 때 (I 초기 쿼리가 빈 문자열이기 때문에이 괜찮다고 생각) 비어있는리스트 결과 :

은 이미 시도에 다음 "SELECT * FROM " + TodoItem.TABLE + " WHERE " + TodoItem.DESCRIPTION + " LIKE \"" + query + "\" LIMIT 5”;

로 변경 LIST_QUERY을 시도하고 쿼리가 업데이트하지 않았거나 목록을 전혀 필터링하지 않은 텍스트를 입력했습니다.

대체 접근법을 시도하고 mapToList 다음에 take (5) (이후 LIMIT 5 이후)를 추가하면 작업이 5 개만 나타납니다. 그리고 나는, (.filter 추가 된 새로운 입력과 안드로이드 스튜디오가 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

이 작업을 수행 할 수있는 몇 가지 방법이 있습니다. 당신이 필터가 자바에 존재하는 원하는 경우에 당신은 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 개 이상의 문자와 일치합니다. _ 와일드 카드는 단일 문자와 일치합니다.

다른 부분은 목록이 제대로 업데이트되지 않는다는 것입니다. 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

나는 혼자서 %를 알아낼 수 있었지만 나머지는 매우 도움이되었습니다. 고맙습니다. –

관련 문제