Как настроить AutocompleteTextView для выполнения только одного поиска по фильтру за раз и установить задержку перед запуском фильтрации?

У меня есть этот вопрос, связанный с AutocompleteTextView. По сути, я реализовал настраиваемый адаптер с настраиваемым фильтром, который фильтрует список настраиваемых объектов, и все работает нормально, за исключением того, что когда я быстро печатаю в autocompleteTextView, кажется, что очередь потоков рабочего фильтра запускается, а сам ввод и фильтрация становится действительно медленным. Как я могу установить только ОДИН фильтр за раз на основе последнего ввода пользователя (таким образом, отменить предыдущий поток фильтра, если он действительно работает) и установить небольшую задержку перед запуском фильтрации, поэтому, когда пользователь быстро печатает, автозаполнение не медленный???

Спасибо!

РЕДАКТИРОВАТЬ: у меня есть этот пользовательский адаптер с реализацией фильтра:

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();
            }
        }           
    }
};
}

Как я могу заставить загрузчик управлять этим рабочим потоком фильтра?


person tonix    schedule 26.03.2014    source источник
comment
оформить заказ stackoverflow.com/a/54840390/4685284   -  person Shahbaz Hashmi    schedule 25.02.2019


Ответы (1)


Лучше всего использовать Loader. При изменении ввода текста перезапустите загрузчик для поиска текущего текста. Поэтому, если уже запущен лодер с таким же идентификатором, он будет перезапущен. Это гарантирует, что вы получите результат последнего ввода. Я использую этот подход в одном из своих приложений в игровом магазине.

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

Примечание: вы можете вызвать перезагрузку для самого первого поиска, он будет создан, если не существует.

Проверьте эту ссылку, если вы не знаете о загрузчике http://developer.android.com/guide/components/loaders.html

person Libin    schedule 27.03.2014
comment
Спасибо за ответ. Я прочитал руководство по загрузчику, которое вы опубликовали. Извините, я хотел бы задать вам несколько вопросов по этой интересной теме. Итак, если загрузчик с таким же идентификатором уже запущен, он будет перезапущен, что означает, что предыдущий загрузчик с тем же идентификатором будет уничтожен и будет создан другой загрузчик с тем же идентификатором (поэтому будет вызываться onCreateLoader())? А почему вы передаете пачку? Обратный вызов может быть вызовом filter() класса Filter??? - person tonix; 28.03.2014
comment
это не полное воссоздание загрузчика, текущая работа будет остановлена ​​и начнется новая работа. bundle предназначен только для передачи данных обратному вызову, он может быть нулевым. - person Libin; 28.03.2014
comment
Итак, если у меня есть фильтр (Charset s), могу ли я сделать что-то вроде: getLoaderManager().restartLoader(0, bundle, myAdapter.getFilter().filter(s)); ? Значит, загрузчик будет запускать фильтрацию? - person tonix; 28.03.2014
comment
Нет, третий аргумент — это обратный вызов загрузчика, чтобы ответить на ответ от загрузчика. - person Libin; 28.03.2014
comment
Извините, я не понял. Как я могу интегрировать этот вызов Loader в свой метод фильтрации (я публикую свой код в метке EDIT). - person tonix; 28.03.2014
comment
developer.android.com/guide/components/loaders.html. проверьте это, у меня есть четкое объяснение - person Libin; 30.03.2014