Android中用RxJava2+Retrofit实现即时搜索时遇InterruptedIOException
RxJava2 + Retrofit 实现即时搜索功能
这是一套完整的即时搜索实现方案,结合你提到的核心操作符,我把代码补全并做了详细拆解:
// 初始化PublishSubject,作为输入事件的流转载体 private PublishSubject<String> searchSubject = PublishSubject.create(); private CompositeDisposable compositeDisposable = new CompositeDisposable(); // 初始化搜索流的核心逻辑 private void initSearchStream() { compositeDisposable.add( searchSubject // 过滤掉无效输入:仅保留长度≥2的非空文本,避免无意义请求 .filter(query -> query.trim().length() >= 2) // 防抖处理:用户停止输入500ms后,才会发送当前输入内容 .debounce(500, TimeUnit.MILLISECONDS) // 切换请求:有新输入时自动取消未完成的旧请求,只保留最新请求的结果 .switchMap(query -> yourRetrofitApi.search(query) // 网络请求放在IO线程执行 .subscribeOn(Schedulers.io()) // 结果回调切换到主线程更新UI .observeOn(AndroidSchedulers.mainThread()) // 局部错误处理:避免单个请求失败导致整个搜索流终止 .onErrorReturn(error -> { // 这里可以返回空列表、错误提示实体等,根据业务需求调整 return new ArrayList<>(); }) ) .subscribe( searchResults -> { // 拿到有效结果后更新UI,比如刷新RecyclerView updateSearchResultsUI(searchResults); }, throwable -> { // 全局错误兜底处理,比如Toast提示搜索失败 showSearchErrorToast(throwable.getMessage()); } ) ); } // 绑定输入框的文本变化事件,调用此方法发送输入内容 public void onSearchInputChanged(String newText) { searchSubject.onNext(newText); } // 在页面销毁时清理订阅,避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); compositeDisposable.clear(); }
关键操作符作用详解
- filter: 拦截短文本或空输入,减少不必要的服务器请求,降低无效流量消耗。
- debounce: 解决连续输入时的频繁请求问题,只有用户停止输入达到设定时长后,才会触发请求,提升用户体验和服务器性能。
- switchMap: 核心的"取消旧请求"逻辑,当新的输入事件到来时,自动取消之前还在pending的网络请求,确保UI始终展示最新的搜索结果,不会出现旧结果覆盖新结果的混乱情况。
额外注意事项
- 错误处理: 一定要在
switchMap内部的网络请求流中添加错误处理(比如onErrorReturn),否则单个请求失败会导致整个搜索流终止,后续输入无法触发请求。 - 生命周期管理: 必须用
CompositeDisposable管理所有订阅,在页面销毁时清理,避免内存泄漏。 - 线程切换: 严格区分IO线程(网络请求)和主线程(UI更新),避免ANR异常和UI操作报错。
内容的提问来源于stack exchange,提问作者Abhishek Tiwari
相关产品推荐
相关产品推荐

