duanshai4484 2016-02-25 21:22
浏览 78
已采纳

键入Android时动态搜索

I have an EditText field for which I implemented an TextChangedListener. In the afterTextChanged method I call a Volley method which sends the text the user has input to my php script which then queries around 20k records in an online mySQL database for all records which have the user input as a prefix. These are then displayed on screen in a ListView to the user. This works very well when I type at a reasonable pace or when I view my results to see if what I am looking for has appeared before typing the next letter. However, if I type the whole word without stopping, or type a whole word, delete it and type a new word very fast, which I'm sure some users will do, the search becomes laggy since so many Volley requests are called. I am thinking about how to improve the efficiency of this, so that even when the user types very fast, these problems won't arise. My code is below:

TEXTCHANGEDLISTENER:

enter_search.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) {
                    if (enter_search.getText().toString().length() >=2) {
                        cityresults.clear();
                        queryCity(enter_search.getText().toString());
                    }
                    else {
                        cityresults.clear();
                        cityresults.add(new City("Please refine your search.",""));
                        ArrayAdapter<City> adapter = new EmptyAdapter();
                        final ListView listView = (ListView) findViewById(R.id.list_view);
                        listView.setAdapter(adapter);
                    }
                }
            });

VOLLEY:

public void queryCity(final String query) {

    request = new StringRequest(Request.Method.POST, SL_URL, new Response.Listener<String>() {
        @Override
        public void onResponse(String s) {
            try {
                cityresults.clear();
                JSONArray jsonArray = new JSONArray(s);
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject a = jsonArray.getJSONObject(i);
                    cityresults.add(new City(a.getString("ascii_name"),(a.getString("timezone"))));
                }
                if (cityresults.isEmpty()) {
                    cityresults.add(new City("Please refine your search.",""));
                    ArrayAdapter<City> adapter = new EmptyAdapter();
                    final ListView listView = (ListView) findViewById(R.id.list_view);
                    listView.setAdapter(adapter);
                }
                else {
                    ArrayAdapter<City> adapter = new MyListAdapter();
                    final ListView listView = (ListView) findViewById(R.id.list_view);
                    listView.setAdapter(adapter);
                }


                }
             catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {

        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("search_query", query);
            return hashMap;
        }
    };
    queue.add(request);
}

展开全部

  • 写回答

1条回答 默认 最新

  • doubu4406 2016-02-25 21:26
    关注

    Even we faced similar kind of issue. What we did was, we put a time period say 1 second or 2 second. So i will call the api whenever there is a time gap of 1 or two seconds between consecutive key events or you can say user takes this much time/pause in typing instead of calling the api everytime something is edited in the edittext.

    editText.addTextChangedListener(
     new TextWatcher() {
      @Override public void onTextChanged(CharSequence s, int start, int before, int count) {}
      @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    
      private Timer timer = new Timer();
      private final long DELAY = 500; // milliseconds
    
      @Override
      public void afterTextChanged(final Editable s) {
       timer.cancel();
       timer = new Timer();
       timer.schedule(
        new TimerTask() {
         @Override
         public void run() {
          // refresh your list
         }
        },
        DELAY
       );
      }
     }
    );
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部