我需要在我的Android应用中实现搜索功能。 API不是一个合适的搜索API,它就像这样
https://example.com/api/list/photos/?start=0&end=30&search=something
所以,基本上,我必须查询每个搜索查询字母的后端,并且端点是分页的,这样我就可以控制要显示的条目数。
我阅读some code使用RxJava为搜索添加时间限制约束,这样我至少可以减少对后端的调用次数。但是我面临的问题是,如果我输入's'请求,如果我输入'so',那么另一个请求就会消失(假设我输入有延迟),所以我可能会得到结果由于某种原因's'之前的'so'然后整个搜索将被打破。此外,如果已经提出请求,响应将在某个时刻到来,我将需要根据该响应更改UI,即使这不是我想要搜索的最终查询。
我正在使用Retrofit 1.9,每当我收到回复时,我都会根据结果更新recyclerView。有没有办法根据上述情况取消Retrofit请求?使这个东西正常工作的最佳设计或实现是什么?任何帮助将受到高度赞赏。
编辑:这是我自己编写的内容。如果能以任何方式改进,请告诉我。
Subscription subscription = RxTextView.textChangeEvents(inputSearch)
.debounce(400, TimeUnit.MILLISECONDS)// default Scheduler is Computation
.filter(new Func1<TextViewTextChangeEvent, Boolean>() {
@Override
public Boolean call(TextViewTextChangeEvent changes) {
return !TextUtils.isEmpty(inputSearch.getText().toString());
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getSearchObserver());
private void getSearchResults(String s) {
LogUtil.i(TAG, "getSearchResults called");
indicator.setVisibility(View.VISIBLE);
DiscoverAPI discoverAPI = restAdapter.create(DiscoverAPI.class);
discoverAPI.getSearchResults(0, 10, s, new Callback<List<Result>>() {
@Override
public void success(List<Result> results, Response response) {
LogUtil.i(TAG, "discover api successful");
list.clear();
if (adapter != null) {
adapter.notifyDataSetInvalidated();
}
list.addAll(results);
if (adapter == null) {
adapter = new SearchGalleryAdapter(TestActivity.this, list);
listView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
indicator.setVisibility(View.GONE);
}
@Override
public void failure(RetrofitError error) {
LogUtil.i(TAG, "discover api failed");
}
});
}
答案 0 :(得分:1)
RxTextView.afterTextChangeEvents(mTextView)
.map(new Func1<TextViewAfterTextChangeEvent, String>() {
@Override
public String call(TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) {
return textViewAfterTextChangeEvent.editable().toString();
}
})
.switchMap(new Func1<String, Observable<SearchResponse>>() {
@Override
public Observable<SearchResponse> call(String query) {
return mApiService.search(query);
}
})
答案 1 :(得分:1)
最后,我找到了解决方案,所以在此发帖以供参考。
RxTextView.textChangeEvents(inputSearch)
.debounce(400, TimeUnit.MILLISECONDS)
.map(new Func1<TextViewTextChangeEvent, String>() {
@Override
public String call(TextViewTextChangeEvent textViewTextChangeEvent) {
return textViewTextChangeEvent.text().toString();
}
})
.switchMap(new Func1<String, Observable<List<Result>>>() {
@Override
public Observable<List<Result>> call(String s) {
DiscoverAPI discoverAPI = restAdapter.create(DiscoverAPI.class);
return discoverAPI.getRxSearchResult(0, 9, s);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getRxSearchObserver());
private Observer<List<Result>> getRxSearchObserver() {
return new Observer<List<Result>>() {
@Override
public void onCompleted() {
LogUtil.i(TAG, "onCompleted called");
}
@Override
public void onError(Throwable e) {
LogUtil.i(TAG, "onError called");
}
@Override
public void onNext(List<Result> results) {
LogUtil.i(TAG, "onNext called");
list.clear();
if (adapter != null) {
adapter.notifyDataSetInvalidated();
}
list.addAll(results);
if (adapter == null) {
adapter = new SearchGalleryAdapter(TestActivity.this, list);
listView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
indicator.setVisibility(View.GONE);
}
};
}
希望它有所帮助。