Как да настроите 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();
            }
        }           
    }
};
}

Как мога да накарам Loader да управлява тази нишка за филтър?


person tonix    schedule 26.03.2014    source източник
comment
плащане stackoverflow.com/a/54840390/4685284   -  person Shahbaz Hashmi    schedule 25.02.2019


Отговори (1)


Най-добрият подход е да използвате Loader. При промяна на въвеждането на текст рестартирайте зареждащото устройство, за да търсите текущия текст. Така че, ако има loder със същия идентификатор, който вече работи, той ще бъде рестартиран. Това ще гарантира, че ще получите резултата от последното въвеждане. Използвам този подход в едно от моите приложения в Play Store.

   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)); ? Значи Loader ще стартира филтрирането? - 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