自动完成延迟

问题描述 投票:2回答:4

我必须为我的应用程序设置自动完成功能。

我已经理解了AutoCompleteTextView操作,但我想动态修改android自动完成使用的String[]

我想做什么:调用一个PHP页面,它将给我一个String[],我将在我的AutoCompleteTextView中使用,但我想只在最后一个键后至少500毫秒按下一个键时才这样做。


EDIT :

好的,我错了。如果在最后一次按下后的500毫秒内按下NO KEY,我想让我的asynctask运行(你知道,通过在输入的每个字符上调用一个请求来避免对我们的服务器过度充电。)


我想我会这样做:

zipBox.setAdapter(myAdapter); //zipBox is an AutoCompleteTextView
zipBox.addTextChangedListener(new TextWatcher(){

    @Override
    public void onTextChanged(CharSequence s,
             int start, int before, int count){

        d = new Date();
        GetAutocompletion ac = new GetAutocompletion();
        ac.execute(zipBox.getText().toString());
    }
    // Other methods to implement
});


private class GetAutocompletion extends AsyncTask<String, String, String>{

    @Override
    protected String doInBackground(String... params){

        //adapter.notifyDataSetChanged();

        try{
             wait(500);
        } catch(InterruptedException e){}

        Date d1 = new Date();

        if(d1.getTime() - d.getTime() > 500){
            String res = "";

            try{

                URLConnection conn = new URL("myUrl.php?term=" + params[0]).openConnection();
                InputStream in = conn.getInputStream();
                Scanner s = new Scanner(in).useDelimiter("\\A");

                while (s.hasNext())
                    res += s.next();

                s.close();
                in.close();

            } catch(Exception e){ Log.d("eduine", "error during autocompletion receive"); }

            return json;
        } else return null;
    }

    @Override
    protected void onPostExecute(String result){

        super.onPostExecute(result);

        Log.d("eduine", "json result : " + result);
    }

}

你怎么看?无论如何我可以使用Timer类吗?

android delay autocompletetextview
4个回答
6
投票

我会在TextWatcher上保留一个名为lastPress的长字段作为字段。按键时,设置lastPress = System.currentTimeMillis()。然后将整个onTextChanged包装在if条件if(System.currentTimeMillis() - lastPress>500)中,并在if if中再次设置lastPress。


new TextWatcher(){
    long lastPress = 0l;
    @Override
    public void onTextChanged(CharSequence s,
             int start, int before, int count){
        if(System.currentTimeMillis() - lastpress > 500){
            lastPress= System.currentTimeMillis();
            GetAutocompletion ac = new GetAutocompletion();
            ac.execute(zipBox.getText().toString());
        }
    }
    // Other methods to implement
}

5
投票

无法评论选择的答案是正确的,所以在这里。只有在指定的延迟结束后按键才能使用此解决方案。如果你写得非常快,然后停止没有请求将被发送到服务器。

您可以使用处理程序并发送延迟的消息来实现:

public void onTextChanged(CharSequence s, int start, int before,
                           int count) {

    final String term = s.toString();
    if( term.length() > 3 ){
        autocompleteHandler.removeMessages(0);
        autocompleteHandler.postDelayed(new Runnable(){
            @Override
            public void run() {
            new SearchLocationAsyncTask(context, term).execute();
        }}, 350);
    }
}

SearchLocationAsynTask调用您的服务器并相应地更新视图。

基本上它的作用是每次文本更改时向处理程序添加一条新消息,如果队列中有任何消息被删除,则添加一条新消息以在350ms内执行。


1
投票

它可以使用处理程序轻松完成。只需要在API调用之前删除所有runnable。下面的代码是相同的

/**
* Created by Shahbaz Hashmi on 12/01/19.
*/
public class AutoCompleteAdapter extends ArrayAdapter<Place> implements Filterable {

private static final String TAG = AutoCompleteAdapter.class.getSimpleName();

private static final int DELAY = 800; // 0.8 seconds delay

private Handler handler;

private Runnable runnable;

private ArrayList<Place> data;
private Context context;
private Location location;
private CompositeDisposable mCompositeDisposable;

public AutoCompleteAdapter(Context context, int resource, Location location) {
    super(context, resource);
    this.context = context;
    this.data = new ArrayList<>();
    this.location = location;
    handler = new Handler();
    mCompositeDisposable = new CompositeDisposable();
}

@Override
public int getCount() {
    return data.size();
}

@Nullable
@Override
public Place getItem(int position) {
    return data.get(position);
}

@NonNull
@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(final CharSequence constraint) {
            final FilterResults results = new FilterResults();
            if (constraint != null) {

                handler.removeCallbacksAndMessages(null);

                mCompositeDisposable.clear();

                handler.postDelayed(runnable , DELAY);

                runnable = new Runnable() {
                    @Override
                    public void run() {
                        ///

                        mCompositeDisposable.add(NetworkClient.getRetrofit().create(NetworkInterface.class)
                                .getPredictions(MapHelper.makeAutocompleteURL((BaseActivity) context, location, constraint.toString(), Config.SEARCH_RADIUS * 1000))
                                .subscribeOn(Schedulers.io())
                                .observeOn(AndroidSchedulers.mainThread()).subscribeWith(new DisposableObserver<PlaceSerializer>(){
                                    @Override
                                    public void onNext(PlaceSerializer placeSerializer) {
                                        LogHelper.d(TAG, "got data form prediction API");
                                        data = new ArrayList<Place>(placeSerializer.getPlaces());
                                        results.values = data;
                                        results.count = data.size();
                                        notifyDataSetChanged();
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        LogHelper.e(TAG, e.getMessage());
                                    }

                                    @Override
                                    public void onComplete() {

                                    }
                                }));

                        results.values = data;
                        results.count = data.size();

                        ///
                    }
                };

            }else{
                if(data.size()>0) data.clear();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                notifyDataSetChanged();
            } else notifyDataSetInvalidated();
        }
    };
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Place place = getItem(position);
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_autocomplete, parent, false);
    }

    TextView primaryText = (TextView) convertView.findViewById(R.id.primary_text);
    TextView secondaryText = (TextView) convertView.findViewById(R.id.secondary_text);

    primaryText.setText(place.getStructuredFormatting().getMainText());
    secondaryText.setText(place.getStructuredFormatting().getSecondaryText());

    return convertView;
  }
}

0
投票

我有同样的问题。数据来了,但autocompleteTextView不会更新。数据未更新的原因是适配器未通知数据集已更改。

 //use this at the initialization part for the autocompleteTextView
 autocompleteTextView.setThreshold(1);
 myAdapter.setNotifyOnChange(true);
 autocompleteTextView.setAdapter(myAdapter);

 // use this when you get new dataset and will show on autocompleteTextView
 myAdapter.notifyDataSetChanged();
© www.soinside.com 2019 - 2024. All rights reserved.