键入 Android 时动态搜索

Posted

技术标签:

【中文标题】键入 Android 时动态搜索【英文标题】:Dynamically Search While Typing Android 【发布时间】:2016-06-09 05:13:46 【问题描述】:

我有一个EditText 字段,为此我实现了一个TextChangedListener。在afterTextChanged 方法中,我调用了一个Volley 方法,该方法将用户输入的文本发送到我的php 脚本,然后在在线mysql 数据库中查询大约20k 条记录,以查找所有以用户输入为前缀的记录。然后这些在屏幕上以ListView 的形式显示给用户。当我以合理的速度输入或查看结果以查看我要查找的内容是否在输入下一个字母之前出现时,这非常有效。但是,如果我不停地输入整个单词,或者输入一个完整的单词,删除它并非常快地输入一个新单词,我相信一些用户会这样做,搜索变得滞后,因为调用了这么多 Volley 请求。我正在考虑如何提高这个效率,这样即使用户打字很快,也不会出现这些问题。我的代码如下:

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);
                    
                
            );

凌空抽射:

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】:

即使我们也遇到过类似的问题。我们所做的是,我们设置了一个时间段,比如 1 秒或 2 秒。所以我会在连续键事件之间有 1 或 2 秒的时间间隔时调用 api,或者你可以说用户在输入时花费了这么多时间/暂停,而不是每次在 edittext 中编辑某些内容时调用 api。

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
   );
  
 
);

【讨论】:

不,这不是你应该遵循的方式,而是使用android.widget.Filter:'''Filtering operations performed by calling filter(CharSequence) or filter(CharSequence, android.widget.Filter.FilterListener) are performed asynchronously. When these methods are called, a filtering request is posted in a request queue and processed later. Any call to one of these methods will cancel any previous non-executed filtering request.'''

以上是关于键入 Android 时动态搜索的主要内容,如果未能解决你的问题,请参考以下文章

Android 在按钮单击时创建 ListView

Android动态搜索的简单实现

Android动态搜索的简单实现

在 WebView Android 中键入时播放声音

Android EditText imeOptions使actionSearch像actionDone一样?

如何将搜索添加到列表视图android,按您的类型对项目进行排序