android - 使用 Retrofit 搜索 api

标签 android retrofit rx-java

我需要在我的 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");
            }
        });
    }

最佳答案

你可以尝试这样的事情:

 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);
            }
        })
  • afterTextChangeEvents 在您的 TextView 上创建文本更改事件流
  • mapTextViewAfterTextChangeEvent 映射到已键入的String
  • switchMap 的工作方式几乎与 flatMap 类似,因此它将您的事件映射到另一个事件流(在本例中为 Api 请求),但是,在发出另一个事件后,它取消订阅之前的流(因此之前的 Api 请求结果将被忽略)

关于android - 使用 Retrofit 搜索 api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36932747/

相关文章:

android - 在 RxJava2 中将 Listener 转换为 Single

java - 如果我在订阅期间出现异常怎么办?

android - 如何在 View 类中获取 Activity 引用?

android - TextWatcher 用于多个 EditText

android - 错误 : No Retrofit annotation found.(参数 #2)

android - Android 中带有 RetroFit2 的 ReactiveLocationProvider 抛出 NetworkOnMainThread

android - 应用程序 SQLite DB 存储在 Android 上的什么位置

java - 自定义 ArrayAdapter 上的 getFilter() 不起作用

android - 改造 1.6 : Call RestService with different (TCP)-Ports

android - 如果发生异常,则将 flatMap 短路