7

カスタム ArrayAdapter を使用して、AutocompleteTextView にアダプターを設定しています (AddressAdapter は ArrayAdapter を拡張します)。

public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> mData;
ArrayList<String> listTempPrefix = new ArrayList<String>();
ArrayList<String> listTemp = new ArrayList<String>();
String valueText;
String[] words;
String ulcase;

public AutoCompleteAdapter(Context context, int textViewResourceId, ArrayList<String> bS) {
    super(context, textViewResourceId);
    mData = bS;//new ArrayList<String>();
}

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

@Override
public String getItem(int index)  
{
    synchronized (listTempPrefix)
    {
        try {
            //Log.e("Error", listTempPrefix.get(index));
            return listTempPrefix.get(index);
        } catch(IndexOutOfBoundsException e) {
            Log.e("Error", "IndexOutOfBoundsException");
            return "";
        }
    }

}

@Override
public Filter getFilter()
{
    Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {

            FilterResults filterResults = new FilterResults();
            synchronized (filterResults)
            {
                listTempPrefix.clear();
                listTemp.clear();
                //Log.e("1", "1");

                try {
                if(constraint != null) {
                    // A class that queries a web API, parses the data and returns an ArrayList<Style>
                    //StyleFetcher fetcher = new StyleFetcher();
                    //try {
                        //mData = fetcher.retrieveResults(constraint.toString());
                    //}
                    //catch(Exception e) {}
                    // Now assign the values and count to the FilterResults object


                    for(String value: mData) {
                        valueText = value.toLowerCase();

                        //System.out.println("constraintH - " + constraint);

                        constraint.toString().toLowerCase();
                        ulcase = constraint.toString().toLowerCase();
                        //System.out.println("ulcase - " + ulcase);

                        if (valueText.startsWith(ulcase)) {
                            listTempPrefix.add(value);
                        } else {
                            words = valueText.split(" ");
                            //final int wordCount = words.length;

                            // Start at index 0, in case valueText starts with space(s)
                            for (int k = 0; k < words.length; k++) {
                                if (words[k].startsWith(ulcase)) {
                                    listTemp.add(value);
                                    break;
                                }
                            }
                        }

                        ///listTemp.add(mData.get(i));
                        //filterResults.count = mData.size();
           //           System.out.println("mData" + i + mData.get(i));
                    }
                    //Log.e("2", "2");
           //       System.out.println("size " + listTemp.size() + " value" + listTemp);

                    listTempPrefix.addAll(listTemp);

                    filterResults.values = listTempPrefix;

                    filterResults.count = listTempPrefix.size();
                    //System.out.println("size " + filterResults.count + " value" + filterResults.values);

                    //System.out.println("constraint" + constraint);

                }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    }
                return filterResults;
            }
        }

        @Override
        protected void publishResults(CharSequence contraint, FilterResults filterResults) 
        {
            synchronized (filterResults)
            {
                if(filterResults != null && filterResults.count > 0) {
                notifyDataSetChanged();
                //Log.e("notifyDataSetChanged", "notifyDataSetChanged");
                }
                else {
                    notifyDataSetInvalidated();
                    //Log.e("notifyDataSetInvalidated", "notifyDataSetInvalidated");
                }
            }
        }
    };
    return myFilter;
}

}

私が時々得たもの:注意してください、それは本当にめったに起こりません. しかし、私はこのバグを完全に取り除きたいと思っています。部分的なスタック トレースは次のとおりです。

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(-1, class android.widget.AutoCompleteTextView$DropDownListView) with Adapter(class com.example.test.AutoCompleteAdapter)].

問題は、キーボードからの高速入力、メソッド notifyDataSetChanged() が呼び出されないことです。しかし、よくわかりません。

4

3 に答える 3

11

publishResults を次のように変更します

@Override 
protected void publishResults(final CharSequence contraint, final FilterResults filterResults) { 
    listTempPrefix = (List) results.values;
    if(filterResults != null && filterResults.count > 0) {
        notifyDataSetChanged();
    } else {
        notifyDataSetInvalidated();
    }
}

このようにして、バックグラウンド スレッドで実行される performFiltering の代わりに、GUI スレッドが結果を更新します。

performFiltering から listTempPrefix 参照を削除し、そこでローカル変数を使用して結果を保存し、FilterResults を介して返します。

于 2013-11-18T20:01:43.997 に答える
8

listTempPrefix(clear と addAll を使用して)配列を変更しているため、この例外を回避performFilteringするには呼び出す必要があります。notifyDataSetChanged

ただしperformFiltering、UI スレッドでは呼び出されないため、呼び出しnotifyDataSetChangedによっても例外が発生します。

この問題を解決する最善の方法は、 内の listTempPrefix 配列を変更してpublishResultsから を呼び出すことnotifyDataSetChangedです。

listTempPrefixメソッドから行った変更を削除しperformFilteringます (フィルター ロジックによっては、一時配列を作成する必要がある場合があります)。

で、に含まれる値で配列を更新し、publishResultsを呼び出します。listTempPrefixfilterResultsnotifyDataSetChanged

コードに基づく例を次に示します。

@Override
public Filter getFilter()
{
    Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {

            FilterResults filterResults = new FilterResults();
            synchronized (filterResults)
            {
                //listTempPrefix.clear(); // Don't change listTempPrefix here
                 ...
                        ulcase = constraint.toString().toLowerCase();
                        //System.out.println("ulcase - " + ulcase);

                        if (valueText.startsWith(ulcase)) {
                            //listTempPrefix.add(value); // Don't change listTempPrefix
                            // To keep your logic you might need an aux array 
                            // for this part
                        } else {
                            ...
                        }

                    //listTempPrefix.addAll(listTemp); // Don't change it

                    filterResults.values = listTempPrefix; // No problem here

                    filterResults.count = listTempPrefix.size(); // No problem here
                    //System.out.println("size " + filterResults.count + " value" + filterResults.values);

                    //System.out.println("constraint" + constraint);

                }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    }
                return filterResults;
            }
        }

        @Override
        protected void publishResults(CharSequence contraint, FilterResults filterResults) 
        {
            // At this point, make the changes you need to listTempPrefix
            // using filterResults.values
            synchronized (filterResults)
            {
                if(filterResults != null && filterResults.count > 0) {
                notifyDataSetChanged();
                //Log.e("notifyDataSetChanged", "notifyDataSetChanged");
                }
                else {
                    notifyDataSetInvalidated();
                    //Log.e("notifyDataSetInvalidated", "notifyDataSetInvalidated");
                }
            }
        }
    };
    return myFilter;
}
于 2012-10-31T11:44:52.520 に答える
0

データセット ( 、、など) が変更を裏付けたらnotifyDataSetChanged()すぐにメソッドを呼び出す必要があります。そうしないと、これで終わります。ArrayListArrayCursorAdapterException

于 2012-10-31T11:00:28.893 に答える