【问题标题】:How to avoid multiple triggers on EditText while user is typing?用户打字时如何避免 EditText 上的多个触发器?
【发布时间】:2012-04-30 07:36:08
【问题描述】:

当用户输入 EditText 时,我使用以下代码执行搜索:

EditText queryView = (EditText) findViewById(R.id.querybox);
queryView.addTextChangedListener(new TextWatcher() {
  @Override
  public void afterTextChanged(Editable s) {
    triggerSearch(s.toString()); 
  }
  @Override
  public void beforeTextChanged(CharSequence s, int start, int count, int after) {
  }
  @Override
  public void onTextChanged(CharSequence s, int start, int before, int count) {
  }
});

但是,当用户键入一个单词时,这会触发多次。也就是说,如果用户输入“hello”,此代码将触发 5 次值(“h”、“he”、“hel”、“hell”、“hello”)。通常,这会很好,但是触发搜索很昂贵,我不想将资源浪费在没有太大用处的中间搜索上。我想要的是在用户开始输入后仅触发某个阈值的侦听器,或者是某种框架,在调用triggerSearch 之前在侦听器中等待,如果在该等待之前触发了另一个事件,则会自行取消。

【问题讨论】:

    标签: android android-edittext


    【解决方案1】:

    由于找不到合适的事件接口,尝试触发延迟搜索。代码实际上非常简单和健壮。

    private final int TRIGGER_SERACH = 1;
    // Where did 1000 come from? It's arbitrary, since I can't find average android typing speed.
    private final long SEARCH_TRIGGER_DELAY_IN_MS = 1000;
    
      private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
          if (msg.what == TRIGGER_SERACH) {
            triggerSearch();
          }
        }
      };
    
     queryView.addTextChangedListener(new TextWatcher() {
    
       @Override
       public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    
       }
    
       @Override
       public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
    
       }
    
       @Override
       public void afterTextChanged(Editable s) {
        handler.removeMessages(TRIGGER_SERACH);
        handler.sendEmptyMessageDelayed(TRIGGER_SERACH, SEARCH_TRIGGER_DELAY_IN_MS);
       });
    

    【讨论】:

    • 这个 Handler 类应该是静态的,否则可能会发生泄漏。
    • @Choletski 请详细说明泄漏是如何发生的,制作静态会防止这种情况发生吗?
    • @jitenagarwal19 静态处理程序不会保留对封闭类的引用
    • 为什么内存泄漏:androiddesignpatterns.com/2013/01/…
    【解决方案2】:

    一种解决方案是不立即执行触发的搜索,而是在调用 onTextChanged 方法后经过一段时间(例如 100 毫秒)后执行触发搜索。此外,每次输入文本时都会重置此间隔。

    这样在用户键入时不会调用触发的搜索。

    【讨论】:

      【解决方案3】:

      在调用triggerSearch之前在监听器中等待;测试Editable s 的长度。

      if(s.length() > THRESHOLD)

      【讨论】:

      • 如何确定合适的阈值?如果用户输入的字数超过阈值,这也不起作用。
      • 您注意到用户没有指定他们触发的搜索。在没有上下文的情况下,我不会推测某些东西过于有限或矫枉过正。您是否考虑过当有人每秒输入少于 10 个字母时,因为您的阈值太短而调用“h”、“he”、“hel”、“hell”、“hello”?这两个答案都是有效的,如果您仍然认为我的答案有冒犯并认为它需要社区审查,请标记我的答案。
      • +1 因为在某些情况下它仍然是最聪明的方法
      【解决方案4】:

      如果您不想在每次按下按钮时触发搜索,那么您需要知道用户何时完成搜索。我会避免试图弄清楚用户何时完成输入的复杂想法。这会导致用户对搜索发生的时间感到困惑。

      简单的答案是放置一个“完成”按钮并在按钮上应用一个 onClickListener 并在那里执行您的搜索。

      最简单的代码: 在xml中

      <Button
      android:onClick="onDoneClicked"
      ... the rest of your button layout
      />
      

      在java中:

      @Override
      public void onDoneClicked(View view){
      EditText queryView = (EditText) findViewById(R.id.querybox);
      triggerSearch(queryView.toString());
      }
      

      【讨论】:

        猜你喜欢
        • 2017-02-03
        • 2021-05-23
        • 2022-11-06
        • 1970-01-01
        • 2016-02-16
        • 1970-01-01
        • 2022-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多