Android中如何优化实时搜索

来源:互联网 发布:苹果电脑如何卸载软件 编辑:程序博客网 时间:2024/06/15 07:56

前言背景

在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<MessageHandler> mMessageHandler;    public CommonHandler(MessageHandler msgHandler) {        mMessageHandler = new WeakReference<MessageHandler>(msgHandler);    }    public CommonHandler(Looper looper, MessageHandler msgHandler) {        super(looper);        mMessageHandler = new WeakReference<MessageHandler>(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。

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

6 0
原创粉丝点击