Android: 当用户暂停输入时,如何向Google API发送请求?

10
我正在开发一个应用程序,用户可以在autoCompleteTextView中输入位置,它将基于谷歌地方API建议位置,如这里所述。
但是我想通过仅在用户停止键入一定时间后发送请求来限制应用程序发送的请求量。有人知道如何做到这一点吗?
4个回答

14

此答案类似,但稍微更加简洁,而且不会引入额外的状态。由于只有在实际需要过滤时才会调用performFiltering,所以您也不需要阈值检查。

似乎只有通过子类化 AutoCompleteTextView 才能实现,因为您不能覆盖/替换由 AutoCompleteTextView 添加的TextWatcher

public class DelayAutoCompleteTextView extends AutoCompleteTextView {           
    public DelayAutoCompleteTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            DelayAutoCompleteTextView.super.performFiltering((CharSequence) msg.obj, msg.arg1);
        }
    };

    @Override
    protected void performFiltering(CharSequence text, int keyCode) {
        mHandler.removeMessages(0);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(0, keyCode, 0, text), 750);
    }
}

我正在使用一个实现了Filterable接口并具有自己的performFiltering方法的AutoCompleteTextView适配器。我能够使用这个设置来实现上述功能吗? - Price
我认为,除非AutoCompleteTextView将内部CharSequence的引用而不是已输入文本的副本传递给您,否则计划的延迟消息和handleMessage()被调用之间键入的任何字符都将丢失。当handleMessage()方法调用performFiltering()时,最安全的方法可能是从View中提取文本。 - Colin M.
@ColinM.,两个事件之间只有短暂的延迟。所以我想基于消息计划时捕获的文本进行过滤可能是可以的。 - Price

4

我已经找到了一个解决上述问题的方案,这个方案运作得非常好。我已经通过以下方式扩展了AutoCompleteTextView。如果有人知道如何进一步改进这段代码,请告诉我。

public class MyAutoCompleteTextView extends AutoCompleteTextView {

// initialization
int threshold;
int delay = 750;
Handler handler = new Handler();
Runnable run;

// constructor
public MyAutoCompleteTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void performFiltering(final CharSequence text, final int keyCode) {
    // get threshold
    threshold = this.getThreshold();

    // perform filter on null to hide dropdown
    doFiltering(null, keyCode);

    // stop execution of previous handler
    handler.removeCallbacks(run);

    // creation of new runnable and prevent filtering of texts which length
    // does not meet threshold
    run = new Runnable() {
        public void run() {
            if (text.length() > threshold) {
                doFiltering(text, keyCode);
            }
        }
    };

    // restart handler
    handler.postDelayed(run, delay);
}

// starts the actual filtering
private void doFiltering(CharSequence text, int keyCode) {
    super.performFiltering(text, keyCode);
}

}

1
谢谢分享。我在https://developers.google.com/places/training/autocomplete-android上使用了这个Google Place API。 - Mark Pazon

0
与上面的答案类似,我发现我需要子类化AutoCompleteTextView。然而,因为我所在的地方互联网速度有点慢,我发现每次用户按键时都要删除延迟处理程序是个问题。所以基本上,如果我只在用户停止输入500毫秒后运行过滤器,结果可能需要几秒钟才能出现,这会让用户感到恼怒。
因此,我不会每次清除处理程序,而是让过滤器每隔几百毫秒运行一次。我的代码比Jan Berkel的代码不太干净。我相信你可以稍微整理一下,但在互联网速度较慢的地区,性能更好。
public class CustomCompleteView extends AutoCompleteTextView{

Handler handler=new Handler();
Runnable r;
boolean cleartogo=false;
boolean pending =false;
CharSequence btext; 
int bkeyCode;
public CustomCompleteView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}

public CustomCompleteView(Context context, AttributeSet attrs)
{
    super(context,attrs);
}
public CustomCompleteView(Context context, AttributeSet attrs, int defStyle)
{
    super(context,attrs,defStyle);
}

@Override
public void performFiltering(CharSequence text, int keyCode){
    if (cleartogo){
        cleartogo=false;
        Log.d(MainActivity.DTAG,"Going to filter on " + text.toString());
        pending=false;
        super.performFiltering(btext, bkeyCode);
    }
    else
    {
        Log.d(MainActivity.DTAG,"Filtering rejected, too soon");
        btext=text;
        bkeyCode=keyCode;
        if (!pending){
        if (r==null)
            r=new MyRunnable(this);
        //try{handler.removeCallbacks(r);} catch (Exception ex){};
        handler.postDelayed(r, 500);
        pending=true;}
    }

}

private class MyRunnable implements Runnable {


CustomCompleteView bc;


    MyRunnable(CustomCompleteView c ) {
        this.bc=c;

    }

    public void run() {
        Log.d(MainActivity.DTAG,"Special Runnable running");
        cleartogo=true;
        bc.performFiltering(btext, bkeyCode);


    }
}

}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接