RxJava 使用debounce操作符 优化app搜索功能

问题

现在几乎所有的App都有搜索功能 , 一般情况我们监听EditText控件,当值发生改变去请求搜索接口. 如:

etKey.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        String key = etKey.getText().toString().trim();
        if (key.length() > 0){
            search(key);// 请求搜索接口,成功后把结果显示到界面上.
        }
    }
});

这样做有两个问题:

  1. 可能导致很多没有意义的请求,耗费用户流量(因为控件的值每更改一次立即就会去请求网络,而且只是最后输入的关键字是有用的)
  2. 可能导致最终搜索的结果不是用户想要的. 例如,用户一开始输入关键字’AB’ 这个时候出现两个请求, 一个请求是A关键字, 一个请求是AB关键字. 表面上是’A’请求先发出去, ‘AB’请求后发出去. 如果后发出去的’AB’请求先返回, ‘A’请求后返回,那么’A’请求后的结果将会覆盖’AB’请求的结果. 从而导致搜索结果不正确.

解决问题

使用强大的RxJava的 debounce操作符 可以解决这个问题。

subscription = RxTextView.textChanges(etKey)
                .debounce(400, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())// 对etKey[EditText]的监听操作 需要在主线程操作
                //对用户输入的关键字进行过滤
                .filter(new Func1<CharSequence, Boolean>() {
                    @Override
                    public Boolean call(CharSequence charSequence) {
                        Log.d("RxJava", "filter is main thread : " + (Looper.getMainLooper() == Looper.myLooper()));
                        return charSequence.toString().trim().length() > 0;
                    }
                })
                .flatMap(new Func1<CharSequence, Observable<List<String>>>() {
                    @Override
                    public Observable<List<String>> call(CharSequence charSequence) {
                        Log.d("RxJava", getMainText("flatMap"));
                        return searchApi.search(charSequence.toString());
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<List<String>>() {
                    @Override
                    public void call(List<String> strings) {
                        tvContent.setText("search result:\n\n");
                        tvContent.append(strings.toString());
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                        tvContent.append("Error:" + throwable.getMessage());
                    }
                });

上面代码的主要逻辑:

  • 使用debounce操作符设置: 只有当用户输入关键字后400毫秒才发射数据[说的直白点就是400毫秒后才会走后面的逻辑];
  • 使用filter操作符 对用户输入的关键字进行过滤:只有输入的关键字不为空,才会走后面的逻辑;
  • 使用flatMap操作符:使用最终的关键字去请求搜索接口

至此,避免EditText每改变一次就请求一次的情况。

但是,还有一个问题,上面说的导致搜索结果的错乱,上面的代码还是没有解决,比如停止输入400毫秒后, 那么肯定会开始请求Search接口, 但是用户又会输入新的关键字,这个时候上个请求还没有返回, 新的请求又去请求Search接口.这个时候有可能最后的一个请求返回, 第一个请求最后返回,导致最终显示的结果是第一次搜索的结果.

怎么去解决这个问题:可以使用switchMap操作符解决。

看看官网对 switchMap操作符 如何解释的:

Returns a new Observable by applying a function that you supply to each item emitted by the source Observable that returns an Observable,
and then emitting the items emitted by the most recently emitted of these Observables.

switchMap操作符 和 flatMap操作符 差不多,区别是switchMap操作符只会发射[emit]最近的Observables。

也就是说,当400毫秒后,发出第一个搜索请求,当这个请求的过程中,用户又去搜索了,发出第二个请求,不管怎样,switchMap操作符只会发射第二次请求的Observable。所以,在上面的代码基础上把flatMap改成switchMap就可以了。

功能实用,真是越来越喜欢RxJava了。

转载:http://blog.csdn.net/johnny901114/article/details/51555203

时间: 2024-08-22 21:27:12

RxJava 使用debounce操作符 优化app搜索功能的相关文章

APP搜索附近功能的一种解决方案-基于百度LBS云服务

为了在APP中根据定位实现搜索附近(POI)的功能,采用百度LBS云服务,将所有POI数据上传后,可以实现该功能. LBS数据管理地址:在这里标记信息后(支持批量上传)即可开始使用搜索功能. http://lbsyun.baidu.com/datamanager/datamanage 搜索附近接口地址: http://api.map.baidu.com/geosearch/v3/nearby 请求方式: GET 参数: { ak:'540b088ff0f926b7d0b6d5a641******

如何通过优化APP截图增加下载率?

很多App开发者都有一个误解:App的搜索排名高,下载量就一定会很客观,即有了排名,就会带来相应的流量.其实排名≠下载率,我们还需要通过优化截图.标题.评论这些方面来提高用户下载率.下面来看看怎么通过优化App截图来增加下载率的! App截图为什么能提高下载率 App截图是向用户展示自己App最直观的一个环节!根据应用商店的展示规则以及用户的使用习惯,用户在找到App的时候,会通过浏览截图来判断App功能.界面这些重要信息,而这也正决定着用户是否会下载App.所以,好的应用截图能给用户展示很多有

Lucene 搜索功能

搜索过程 图解: 主要 API: IndexSearcher:    //所有搜索都通过 IndexSearcher 进行,他们将调用该类中重载的 search() 方法 Query:            //封装某种查询类型的具体子类,Query 实例将会被传递给 IndexSearcher 的 search() 方法 QueryParser:      //将用户输入的查询表达式处理成各种具体的 Query 对象 TopDocs:          //保存由 IndexSearcher.

Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音

转载请注明出处:http://blog.csdn.net/xiaanming/article/details/12684155 前段时间因为换工作的缘故又恰巧碰到国庆节,所以有段时间自己没有更新博客了,过完国庆到新公司报道,感觉还不错,就是现在住的地方离新公司有点远,地铁20站,伤不起啊,我每天早上7点多就要起床,然后屁颠屁颠的去挤地铁上班,晚上下班还要挤地铁,先不说路程远,车费一天就要10几块,我的银子啊,有坐龙华线去上班的深圳程序员不?听说那条线上班高峰期很挤?我没在上班高峰期坐过那趟车,我

iOS9系列专题二——全新的搜索功能api

更加智能的搜索方案--iOS9搜索功能新api 一.引言 iOS9中为我们提供了许多新的api,搜索功能的加强无疑是其中比较显眼的一个.首先,我们先设想一下:如果在你的app中定义一种标识符,在siri和搜索中,可以用过这个标识符搜索到你的app,是不是很棒?不,这还差得远,你可以定义任意的数据,使其在搜索和siri中可以快速检索到,这样的搜索功能是不是非常酷?不,还有更cool的,你甚至可以在你的网站中添加一些标志,使apple的爬虫可以检索到,那样,即使用户没有安装你的app,也可以在搜索中

js搜索框实现自动搜索功能

做项目的时候,老板让我自己封装一个搜索功能,就类似于百度这种 输入了字符之后,就可以自动搜索数据,而且还会出现一个下拉框供用户选择,我觉得我老板有问题,网上有这么多插件,不仅封装好了,性能也做了优化,什么功能都有,他不用,一定要我用原生js写,写毛线写,我内心吐槽了很久,不过还是要做,为了工资而低头,所以我这个小白就硬着头皮写完了,肯定有很多不足,也没有封装,就是想到哪里写到哪里,给大家当反面教材看看,如果大家看见了,也可以指点指点我,让我进步 由于我是在项目里写的,所以有很多东西和大家的肯定不

利用solr实现商品的搜索功能

Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展,并对索引.搜索性能进行了优化. Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务.有效降低频繁访问数据库对数据库造成的压力. 第一步:将solr部署在linux系统下. 第二步:solrJ是solr的客户端,使用它需要依赖solrJ的jar包. 第三步:将数据库的内容添加到solr的索引库,这样查询就在索

Android搜索功能的案例,本地保存搜索历史记录......

开发的APP有一个搜索功能,并且需要显示搜索的历史记录,我闲暇之余帮她开发了这个功能,现把该页面抽取成一个demo分享给大家. 实现效果如图所示:  本案例实现起来很简单,所以可以直接拿来嵌入项目中使用,涉及到的知识点: - 数据库的增删改查操作 - ListView和ScrollView的嵌套冲突解决 - 监听软键盘回车按钮设置为搜索按钮 - 使用TextWatcher( )实时筛选 - 已搜索的关键字再次搜索不重复添加到数据库 - 刚进入页面设置软键盘不因为EditText而自动弹出 代码

IOS-5个可以帮你优化App的优秀网站

也许现在有一款App可以提供所有你需要的,你不需要的,或者你可以想象到的内容.但是,有多少App真的可以不仅满足需求而且还能提供很好的用户体验呢? 相信很多APP并没有这样的能力.有一些APP的设计特别烂,以至于用户很难去完成一些操作.也有一些APP,当用户做了一些操作之后,动不动就挂掉了.还有一些APP设计的很不直观,很难去操作.所以我想当我说避免开发出一款平庸的APP是一件亟待解决的事情的时候,你会同意我的观点.如果你正在寻找一些工具去优化你的APP, 你会很开心的发现其实这样的工具还挺多的