我必须为我的应用程序设置自动完成功能。
我已经理解了AutoCompleteTextView操作,但我想动态修改android自动完成所使用的String[]
。
我想做什么:调用一个PHP页面,它会给我一个String[]
我将在我的AutoCompleteTextView中使用,但我只想在最后一个按键后至少500毫秒按下一个键
好的,我错了。如果在最后一次按下后的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类吗?
答案 0 :(得分:6)
我将一个名为lastPress的长名称作为TextWatcher上的字段。按某个键时,设置lastPress = System.currentTimeMillis()
。然后将整个onTextChanged包装在条件为if(System.currentTimeMillis() - lastPress>500)
的if中,并在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
}
答案 1 :(得分: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内执行。
答案 2 :(得分: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();
答案 3 :(得分:0)
可以使用处理程序轻松完成。只需在调用API之前删除所有可运行的对象。下面的代码是相同的
/**
* 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;
}
}
答案 4 :(得分:0)
我可能在聚会上迟到了,但我已经实现了类似的场景,如果用户输入文本,监听器将不会执行任何操作,直到用户停止输入。一旦用户停止输入,就会执行一个代码模块。但是如果用户再次输入文本,即使在指定时间过去前一个字符,设置的时间也会刷新。
下面是我使用的方法, 我用的是 RXBinding,很简单。
依赖:::
implementation 'com.jakewharton.rxbinding:rxbinding:0.4.0'
代码做文本观看 :::
RxTextView.textChanges(mEdtNo1)
.debounce(TIME_DELAY, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
charSequence -> {
//YOUR CODE WHICH NEED TO BE PERFORMED AFTER USER DONE TYPING WILL BE HERE...
}
);
在上面的代码中,