简体   繁体   English

如何设置AutocompleteTextView一次仅执行一个过滤器搜索并设置开始过滤之前的延迟?

[英]How to set AutocompleteTextView to perform only one filter search at a time and set a delay before starting the filtering?

I have this question related the AutocompleteTextView. 我有这个问题与AutocompleteTextView有关。 Basically I have implemented a custom adapter with a custom Filter which filters a list of custom objects and all is working fine except that when I type in a fast way in the autocompleteTextView seems like a queue of worker filter threads starts and the typing and filtering itself becomes really slow. 基本上,我已经实现了带有自定义过滤器的自定义适配器,该过滤器过滤了一系列自定义对象,并且一切正常,只是当我在autocompleteTextView中以快速方式键入时,似乎好像启动了工作过滤器线程队列,并且键入和过滤本身变得很慢。 How can I set only ONE filter at a time based on the latest input of the user (thus cancel the previous filter thread if it actually runs) and set a small delay before starting the filtering so when the user types fast the autocomplete doesn't slow??? 如何根据用户的最新输入一次只设置一个过滤器(如果实际运行,则取消上一个过滤器线程),并在启动过滤之前设置一个小的延迟,以便当用户快速键入时,自动完成功能不会慢???

Thanks! 谢谢!

EDIT: I have this custom adapter with a Filter implementation: 编辑:我有此自定义适配器与筛选器实现:

public class MunicipalitySearchAdapter extends ArrayAdapter<Municipality> {

private ArrayList<Municipality> municipalities;
private ArrayList<Municipality> allMunicipalities;
private ArrayList<Municipality> suggestedMunicipalities;

private List<Trieable> triableList;

private Trie municipalityTrie;

private int viewResourceId;

@SuppressWarnings("unchecked")
public MunicipalitySearchAdapter(Context context, int viewResourceId, ArrayList<Municipality> municipalities) {
    super(context, viewResourceId, municipalities);
    this.municipalities = municipalities;
    this.allMunicipalities = (ArrayList<Municipality>) this.municipalities.clone();
    this.suggestedMunicipalities = new ArrayList<Municipality>();
    this.viewResourceId = viewResourceId;
    this.triableList = new ArrayList<Trieable>();
    for (Municipality mun : allMunicipalities) {
        triableList.add(mun);
    }
    municipalityTrie = new Trie(triableList, Locale.ITALY);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(this.viewResourceId, null);
    }
    Municipality municipality = municipalities.get(position);
    if (municipality != null) {
        TextView munNameTxtView = (TextView) v.findViewById(R.id.name);
        TextView proSignTxtView = (TextView) v.findViewById(R.id.sign);
        TextView regNameTxtView = (TextView) v.findViewById(R.id.regionName);

        if (munNameTxtView != null) {
            munNameTxtView.setText(municipality.getName());
        }
        if (proSignTxtView != null) {
            proSignTxtView.setText(municipality.getProvinceSign());
        }
        if (regNameTxtView != null) {
            regNameTxtView.setText(municipality.getRegionName());
        }
    }
    return v;
}

@Override 
public Filter getFilter() {
    return municipalityFilter;
}

Filter municipalityFilter = new Filter() {      
    CharSequence filterConstraint;
    @Override
    public String convertResultToString(Object resultValue) {
        String str = ((Municipality) (resultValue)).getName();
        return str;
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults filterRes = new FilterResults();
        synchronized (filterRes) {
            if (this.filterConstraint == null) {
                this.filterConstraint = constraint;
            }

            if (constraint == null || constraint.length() == 0) {
                filterRes.values = allMunicipalities;
                filterRes.count = allMunicipalities.size();
            }

            else {
                String constraintString = constraint.toString().trim().toLowerCase(Locale.ITALY);
                suggestedMunicipalities.clear();

                List<Integer> wordsIndexesList = municipalityTrie.getWordsIndexes(municipalityTrie.getRootVertex(), constraintString);
                for (int index : wordsIndexesList) {
                    suggestedMunicipalities.add(allMunicipalities.get(index));
                }

                List<Integer> prefixesIndexesList = municipalityTrie.getPrefixesIndexes(municipalityTrie.getRootVertex(), constraintString);
                for (int index : prefixesIndexesList) {
                    suggestedMunicipalities.add(allMunicipalities.get(index));
                }

                filterRes.values = suggestedMunicipalities;
                filterRes.count = suggestedMunicipalities.size();                   
            }
        }

        return filterRes;

    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if (results != null && results.count > 0) {
            synchronized (results) {
                @SuppressWarnings("unchecked")
                ArrayList<Municipality> filteredMunicipalities = (ArrayList<Municipality>) results.values;
                ArrayList<Municipality> supportMunicipalitiesList = new ArrayList<Municipality>();

                clear();
                for (Municipality mun : filteredMunicipalities) {
                    supportMunicipalitiesList.add(mun);
                }
                Iterator<Municipality> municipalityIterator = supportMunicipalitiesList.iterator();
                while (municipalityIterator.hasNext()) {
                    Municipality municipality = municipalityIterator.next();
                    add(municipality);
                }
                notifyDataSetChanged();
            }
        }           
    }
};
}

How can I make a Loader manage this filter worker thread? 如何使Loader管理此过滤器工作线程?

Best approach is to use Loader. 最好的方法是使用Loader。 On textinput change restart the loader to search for the current text. 在textinput更改时,重新启动加载程序以搜索当前文本。 So if there is a loder with same Id is already running it will be restarted. 因此,如果已经有一个具有相同ID的Loder已在运行,它将重新启动。 This will make sure you will get the result of last input . 这将确保您得到最后输入的结果。 I am using this approach in one of my app in play store. 我在Play商店的一个应用中使用了这种方法。

   getLoaderManager().restartLoader(0, bundle, callback);
 // 0 - I'd
// pass the input text through bundle
// callback - loader callback

Note : you can call restart for the first search itself, it will be created if not exist. 注意:您可以为第一个搜索本身调用重新启动,如果不存在,它将被创建。

Check this link if your not aware of loader http://developer.android.com/guide/components/loaders.html 如果您不知道加载器,请检查此链接http://developer.android.com/guide/components/loaders.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM