android 快速检索,Android中如何优化实时搜索

前言背景

在App开发过程中,搜索功能是必不可少的。一般对于搜索功能,要么是输入一段文字后自己手动点击搜索按钮进行搜索;要么是实时的搜索。如果输入框中每一个字符的改变都要去触发网络请求的话,会浪费用户的流量,增大服务器的负载,并且使页面比较卡顿。这显然是不可取的。举一个很简单的例子,用户想要搜索 "ABC" ,如果我们直接用TextWatcher监听里面的afterTextChanged(Editable s)方法来处理的话,会向服务器发送3次请求。显然这会造成差的用户体验并浪费网路资源。

失败的实现方式

显然我们还是要从TextWatcher 这个监听下做文章,下面是实时搜索失败的实现方式。

/**

* EditText 设置的监听

*

*/

private TextWatcher mSearchWatch = 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 searchword = s.toString().trim();

Log.e("tianzhu", searchword);

startSearch(searchword);

}

};

/**

* 开始P层搜索

*

*/

private void startSearch(String keyword) {

if (TextUtils.isEmpty(keyword)) {

return;

}

mPresenter.searchData(keyword);

mSearchEdit.clearFocus();

}

在上面的方式中,每一个字符的改变都要去触发网络请求的话,会浪费用户的流量,增大服务器的负载,并且使页面比较卡顿。

优化的实现方式

我们可以思考,既然每次文本框的改变都会回调 afterTextChanged(Editable s) ,我进行优化的策略是当EditText中两次改变在 500ms 内不会触发搜索。当输入框文字在500ms 内未发生改变时,再触发搜索。

/**

* EditText 设置的监听

*

*/

private TextWatcher mSearchWatch = 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 searchword = s.toString().trim();

//我们可以把每次输入框改变的字符串传给一个工具类,并让它来判断是否进行搜索

mOptionSearch.optionSearch(searchword);

Log.e("tianzhu", searchword);

}

};

/**

* 开始P层搜索

*

*/

private void startSearch(String keyword) {

if (TextUtils.isEmpty(keyword)) {

return;

}

mPresenter.searchData(keyword);

mSearchEdit.clearFocus();

}

@Override

public void getKeyword(String keyword) {

//开始搜索

if (!TextUtils.isEmpty(keyword) && mPresenter != null) {

startSearch(keyword);

}

}

**

* Created by tianzhu on 17/3/15.

* 搜索优化,快速点击不会一直触发搜索,这也是最关键的类

*/

public class OptionSearch implements CommonHandler.MessageHandler {

private String currentWord;

private IFinishListener mListener;

private MyRunnable myRunnable = new MyRunnable();

private CommonHandler mHandler;

/**

* 点击按钮响应间隔时间-毫秒

*/

private int INTERVAL_TIME = 500;

public OptionSearch(Looper looper) {

mHandler = new CommonHandler(looper, this);

}

/**

* 这一步就是实时搜索优化的关键代码了,当EditText中的文字发生改变时,我们先会将handle中的Callback移除掉。然后使用Handle发一个延时的消息。最后通过回调getKeyword,让Activity开始搜索

*/

public void optionSearch(String keyword) {

this.currentWord = keyword;

if (myRunnable != null) {

mHandler.removeCallbacks(myRunnable);

}

mHandler.postDelayed(myRunnable, INTERVAL_TIME);

}

public void setListener(IFinishListener listener) {

this.mListener = listener;

}

@Override

public void handleMessage(Message msg) {

if(mListener!=null){

mListener.getKeyword(currentWord);

}

}

public interface IFinishListener {

void getKeyword(String keyword);

}

private class MyRunnable implements Runnable {

@Override

public void run() {

mHandler.sendEmptyMessage(1);

}

}

}

/**

* Created by tianzhu on 2016/07/19.

* 防止内存泄露handle

*/

public class CommonHandler extends Handler {

public interface MessageHandler {

void handleMessage(Message msg);

}

private WeakReference mMessageHandler;

public CommonHandler(MessageHandler msgHandler) {

mMessageHandler = new WeakReference(msgHandler);

}

public CommonHandler(Looper looper, MessageHandler msgHandler) {

super(looper);

mMessageHandler = new WeakReference(msgHandler);

}

@Override

public void handleMessage(Message msg) {

MessageHandler realHandler = mMessageHandler.get();

if (realHandler != null) {

realHandler.handleMessage(msg);

}

}

}

总结

1.在用户快速输入的过程中不触发搜索

2.使用弱引用避免Handler内存泄露

3.使用Handler的 postDelayed 方法 发送延时消息。当用户快速输入时,使用mHandler.removeCallbacks(myRunnable),将当前Handler的中的Callback移除。重新发一个postDelayed。

这样就做到了实时搜索的,小伙伴们赶紧试试吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值