项目里有这么一个需求,如果用户进入一个搜索页面,页面顶端有一个搜索框,用户在输入的同时,底下同步的展示相关搜索建议。大约是这个样子:

大体逻辑如下:

实现功能:在输入的同时根据输入的文字立即给出结果,服务器端使用solaris做内存上的缓存。

关键地方在于:

1、用户输入完毕之后要尽可能快的响应

2、尽可能的为搜索服务器降低压力

3、将网络带宽资源最大化的用在用户真正需要的搜索结果上

注:本文只讨论客户端的优化,服务器搜索优化暂不涉及

这个功能出现了很久,直到最近才开始修改,并且连改三个版本

第一版:监听EditTextView的TextChanged事件,每次当用户在搜索框输入或者删除一个字符,就用当前输入框里的文字发起一次搜索请求,并在请求结束后的回调函数中,判断之前请求的文字和当前输入框里文字是否相同,如果相同就显示

优点:实时性强,用户输入完毕之后立刻发出请求,不需等待

缺点:由于http请求线程池有限,允许的并发量很小,也许新请求的关键字需要排队,也就是等之前关键字搜索完毕之后再进行请求,实际上用户等待的时间会很长。并且给搜索服务器带来了极大的压力

第二版:设置一个定时器,每1.5s检测一下搜索框中的内容,如果内容发生改变,就发起一次Http请求,并通过OkHttp将之前全部的关键字请求都取消掉,减少并发。

优点:减少了并发Http请求的队列等待,为服务器减少了压力

缺点:1.5秒的扫描间隔比较长,用户需要多付出无谓的1.5s等待时间,极大的降低了用户体验

第三版:启动一个子线程进行维护,用户每输入一个字母后等待500ms,如果500ms内用户没有输入其他字符,就搜索当前搜索框里的文字,如果500ms以内用户又继续输入了文字,就重新开始500ms的等待

第四版:策略与第三版相同,但是不使用子线程进行维护,而是使用Android原生的Handler和MessageQueue队列进行维护,减少线程的内存开销和线程之间的同步问题

下面搬上源代码:

第一版源码:简单实现TextChanged监听器

headerEditText.addTextChangedListener(new TextWatcher() {//EditText的文字改变监听事件@Overridepublic void onTextChanged(CharSequence constraint, int start, int before, int count) {//发起Http请求}@Overridepublic void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}@Overridepublic void afterTextChanged(Editable s) {}});

第二版源码:在第一版的基础上加入了TimerTask实现定时扫描

String searchKeyWord;//用于在500ms内缓存用户输入的关键字
String lastSearchWord;//上次搜索成功的关键字/*** 用于取消没有执行完的搜索请求* @return*/@Overridepublic String getHttpTaskKey() {return this.getClass().getName();}class RestaurantSuggestionTask extends TimerTask {@Overridepublic void run() {JLogUtils.i("AlexHttp","1.5s等待结束,当前的关键字"+searchKeyWord);if(searchKeyWord==lastSearchWord)return;//如果500ms以内,用户没有写过别的字,就不发起新的搜索lastSearchWord = searchKeyWord;//清除掉之前没有完成的搜索请求if(searchFindActivity!=null)HttpTaskHandler.getInstance().removeTask(searchFindActivity.getClass().getName());getAllSearchTextFilter(searchKeyWord);//发起Http请求}}Timer searchTimer = null;private void getAllSearchTextFilter(final String keyword) {JLogUtils.i("MartinFilter", "getAllSearchTextFilter keyword=>" + keyword);searchKeyWord = keyword;if(searchTimer!=null)return;searchTimer = new Timer();try {searchTimer.scheduleAtFixedRate(new RestaurantSuggestionTask(),0,1500);} catch (Exception e) {JLogUtils.i("AlexHttp","搜索餐馆出现异常"+keyword,e);}}@Overridepublic void onStop() {super.onStop();//停止搜索关键字监听器if(searchTimer!=null)searchTimer.cancel();searchTimer = null;}

第三版源码:去掉定时更新的方案,采用500ms自动延迟,并使用子线程维护

String searchKeyWord;//用于在500ms内缓存用户输入的关键字
String wordSearching;//正在搜索的关键字/*** 用于取消没有执行完的搜索请求* @return*/@Overridepublic String getHttpTaskKey() {return this.getClass().getName();}class SearchThread extends Thread{String keyWord;private int waitTime = 500;Handler handler = new Handler();public void pushKeyWord(String keyWord){this.keyWord = keyWord;waitTime = 500;}@Overridepublic void run() {super.run();while(waitTime > 0){//逐步倒计时,如果有新的关键字,就恢复500ms等待try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}waitTime-=100;}if(searchFindActivity!=null)HttpTaskHandler.getInstance().removeTask(searchFindActivity.getClass().getName());handler.post(new Runnable() {@Overridepublic void run() {TMPSearchFindSuggestionFilterKeywordsEntity filterKeywordsEntity = getLatestKeyFilterDeletePreviousFilters();//此处发起Http请求searchThread = null;}});}}SearchThread searchThread = null;private void getAllSearchTextFilter(final String keyword) {JLogUtils.i("MartinFilter", "getAllSearchTextFilter keyword=>" + keyword);//清除掉之前没有完成的搜索请求if(keyword==null)return;if(searchFindActivity!=null && !keyword.equals(wordSearching))HttpTaskHandler.getInstance().removeTask(searchFindActivity.getClass().getName());searchKeyWord = keyword;if(searchThread!=null){searchThread.pushKeyWord(keyword);return;}searchThread = new SearchThread();searchThread.start();}@Overridepublic void onStop() {super.onStop();//停止搜索关键字监听器if(searchThread!=null)searchThread.interrupt();searchThread = null;}

第四版源码:不使用子线程进行维护,而使用Handler减少子线程的建立

这里的方案是,在Fragment中有一个Runnable实例,它的Run方法就是请求Http的代码,每次在搜索框输入文字的时候,就用Handler先把之前放到MessageQueue的Runnable移除,然后把新的Runnable放进去(其实是同一个实例),分别调用的是handler.removeTask(Runnable)和handler.postDelay(Runnable,500);这样就实现了通过一个队列去管理输入文字的搜索。

如果用户输入的比较慢,假设700ms才输入一个字符,那么在新字符输入的过程中,所有旧的没有锁完的关键字的请求会被通过OkHttp cancel掉

SearchRunnable searchRunnable = new SearchRunnable();class SearchRunnable implements Runnable{String keyWord;Handler handler = new Handler();public void pushKeyWord(String keyWord){this.keyWord = keyWord;handler.removeCallbacks(this);handler.postDelayed(this,500);}@Overridepublic void run() {TMPSearchFindSuggestionFilterKeywordsEntity filterKeywordsEntity = getLatestKeyFilterDeletePreviousFilters();//此处发起Http请求wordSearching = searchKeyWord;}}private void getAllSearchTextFilter(final String keyword) {JLogUtils.i("MartinFilter", "getAllSearchTextFilter keyword=>" + keyword);//清除掉之前没有完成的搜索请求if(keyword==null)return;if(searchFindActivity!=null && !keyword.equals(wordSearching))HttpTaskHandler.getInstance().removeTask(searchFindActivity.getClass().getName());searchKeyWord = keyword;searchRunnable.pushKeyWord(keyword);}@Overridepublic void onStop() {super.onStop();}

看看实际操作打印出来的Log

07-11 11:56:08.061 28267-28267/? I/AlexHttp: 收到信息的关键字c
07-11 11:56:08.218 28267-28267/? I/AlexHttp: 收到信息的关键字ch
07-11 11:56:08.541 28267-28267/? I/AlexHttp: 收到信息的关键字chi
07-11 11:56:08.873 28267-28267/? I/AlexHttp: 收到信息的关键字chin
07-11 11:56:09.112 28267-28267/? I/AlexHttp: 收到信息的关键字chine
07-11 11:56:09.321 28267-28267/? I/AlexHttp: 收到信息的关键字chines
07-11 11:56:09.528 28267-28267/? I/AlexHttp: 收到信息的关键字chinese
07-11 11:56:10.029 28267-28267/? I/AlexHttp: 搜索餐馆提示的接口=>http://staging.xxx.com:8033/search/filtergroupedname?v=2.6.7&client=1&cityID=2&filterWord=chinese
07-11 11:56:10.029 28267-28267/? I/AlexHttp: 准备访问get接口http://staging.xxx.com:8033/search/filtergroupedname?v=2.6.7&client=1&cityID=2&filterWord=chinese
07-11 11:56:10.467 28267-28267/? I/AlexHttp: 请求完毕,准备释放内存
07-11 11:56:10.467 28267-28267/? I/AlexHttp: 访问get接口成功

Android支持单词提示搜索框的网络请求策略相关推荐

  1. android 仿搜索动画,Android仿京东顶部搜索框滑动伸缩动画效果

    最近使用京东发现,京东顶部的搜索框有一个新的伸缩效果,根据用户的手势滑动,伸缩搜索框.觉得效果还不错,就看了下其他的应用有没有这种伸缩的效果,发现安居客也使用了类似的一种效果,然后就想着实现这样的一种 ...

  2. Android——高德地图地点搜索框

    效果图 首先 实现效果如图.由于搜索采用的是 高德地图搜索 SDK 所以需要到 高德地图开发者注册账号 获取到 appKey 注册成功进入个人中心 创建对应的应用 build.gradle 创建项目, ...

  3. android 仿简书评论,Android仿简书搜索框效果的示例代码

    前言 之前用简书的时候一直是在web端,后来下载了客户端,看到了搜索的那个动画,就尝试的去写了,没写之前感觉挺容易的,写了之后,就感觉里面还是有些要注意的东西的.话不多说,直接上图. Activity ...

  4. android自定义搜索栏,Android自定义View实现搜索框(SearchView)功能

    概述 在Android开发中,当系统数据项比较多时,常常会在app添加搜索功能,方便用户能快速获得需要的数据.搜索栏对于我们并不陌生,在许多app都能见到它,比如豌豆荚 在某些情况下,我们希望我们的自 ...

  5. Android RxJava操作符的学习---功能性操作符--网络请求出错重连(结合Retrofit)

    1. 需求场景 2. 功能说明 功能需求说明 功能逻辑  实例说明 在本例子中:采用Get方法对 金山词霸API 发送网络请求 通过 断开网络连接 模拟 网络异常错误(恢复网络即可成功发送请求) 限制 ...

  6. Android RxJava操作符的学习---变换操作符---网络请求嵌套回调

    变换操作符的主要开发需求场景 = 嵌套回调(Callback hell) 下面,我将采用一个实际应用场景实例来讲解嵌套回调(Callback hell) 1. 需求场景 1.1 背景 需要进行嵌套网络 ...

  7. Android 获取当前网速质量调整网络请求

    在开发中,有时候常常需要根据用户当前的网速来做一些操作,比如图片的加载,当网速非常好的时候,比如连接的是wifi,我们就会下载高分辨率的图片,反之,当用户使用的是2g网时,我们则给他下载低分辨率的小图 ...

  8. Android AutoCompleteTextView自动提示文本框

    效果 使用方法: 在布局文件中: <AutoCompleteTextViewandroid:id="@+id/autotextview"android:completionT ...

  9. android之 实现对搜索框输入内容(自动出现匹配内容)

    <AutocompleteTextView>:自动生成视图标签 <MultiAutoCompleteTextView>:可以实现多次匹配 android:completionT ...

最新文章

  1. Windows下安装Object C开发环境,及Hello Word(转)
  2. 【数学基础】拉格朗日对偶
  3. Ubuntu下安装Pycharm及相关设置
  4. Jquery一些常见性能的问题
  5. java 静态缓存示例_Java 9 JShell示例:集合静态工厂方法
  6. Linux 多线程开发-等待线程结束pthread_join
  7. mysql xdevapi_MySql Connector/C++8简介
  8. Springboot应用中线程池配置教程(2021版)
  9. 组装r730服务器,戴尔poweredge r730服务器配置及系统安装详解教程
  10. 快速上手!mysql数据恢复的方法
  11. 兄弟打印机内存已满清零方法_brother打印机怎么清零?brother打印机清零方法
  12. 从区划边界geojson中查询经纬度坐标对应的省市区县乡镇名称,开源Java工具,内存占用低、高性能
  13. html自动选择省市,jQuery中国省市区地址三级联动插件Distpicker
  14. RuntimeError: CUDA error (10): invalid device ordinal
  15. phpstorm php代码补全,基本代码补全:补全名称和关键字
  16. dell r720xd 裸机配置系列 3 配置网络
  17. C语言,百马百担暴力秒懂,有100匹马,驮100担货,大马驮3担,中马驮2担,两匹小马驮1担,要求一次性驮完,请问大马、中马、小马各几匹?
  18. 金融信创虽风正时济,应对挑战该如何乘风破浪(一)
  19. struts1 标签
  20. Bootstrap教程简介

热门文章

  1. java下拉框怎么写,java下拉框怎么写
  2. 备战蓝桥 Day01 | 世界末日问题
  3. 关于前端position属性和display属性,这篇文章已足够
  4. background与background-color 你“不知道”的区别
  5. 云探校,VR全景打造线上可视化校园
  6. 学生用计算机排行,2017学生笔记本电脑排行
  7. 利用python编写祝福短信_python实现祝福弹窗效果
  8. java数组中常见操作1——遍历
  9. IT男的”幸福”生活续1
  10. 学生选课在MYSQL创建表_学生选课数据库SQL语句练习题