Chức năng search với RxJava.
Search là một fuction phổ biến mà hầu hết các ứng dụng đều cần. Chúng ta cùng nhìn lại cách thức mà chứng ta thường implement một fuction search trong ứng dụng searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean ...
Search là một fuction phổ biến mà hầu hết các ứng dụng đều cần. Chúng ta cùng nhìn lại cách thức mà chứng ta thường implement một fuction search trong ứng dụng
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return true; } @Override public boolean onQueryTextChange(String newText) { if (!newText.isEmpty()) { searchData(newText); // call api search data } return true; } });
ở ví dụ trên chúng ta có thể nhận thấy mỗi khi chúng ta thay đổi text trên searchview thì đều thực hiện request đến server để thực hiện lấy dữ liệu. Việc tạo quá nhiều reuquest đến server quả thực là một điều không tốt . Vậy có cách nào chúng ta có thể tránh việc này xảy ra. Có rất nhiều cách để giải quyết được vấn đề này đơn giản chúng ta có thể check thời gian gọi api để thực hiện delay cho mỗi lần gọi hoặc cũng có thể sử dụng rxjava, rxbinding để giải quyết vấn đề này . Trong bài viết này mình sẽ giới thiệu đến các bạn cách sử dụng rxjava và rxbinding để làm việc với searchview.
Sử dụng rxjava thì chắc chắn việc đầu tiền chúng ta nghĩ đến là tạo một Observable. Ở đây mình sẽ tạo một Observable emit ra text trên searchview
public class RxSearch { public static Observable<String> fromSearchView(@NonNull final SearchView searchView) { final BehaviorSubject<String> subject = BehaviorSubject.create(""); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { subject.onCompleted(); return true; } @Override public boolean onQueryTextChange(String newText) { if (!newText.isEmpty()) { subject.onNext(newText); } return true; } }); return subject; } }
Thực hiện bắt sự thay đổi của searchview
RxSearch.fromSearchView(searchView) .debounce(300, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(query -> { searchData(newText); // call api search data });
Ở đây chúng ta sẽ sử dụng operator debounce để delay việc call api
Có một cách đơn giản hơn rất nhiều đó là sử dụng thêm một thư viện là RxBinding
RxTextView.textChanges(searchTextView) .filter(new Func1<String, Boolean> (){ @Override public Boolean call(String s) { return s.length() > 2; } }) .debounce(100, TimeUnit.MILLISECONDS) .switchMap(new Func1<String, Observable<List<Result>>>() { makeApiCall(s); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(/* attach observer */);