ArrayAdapterの実際のソースコードを調べたところ、実際にはそのように動作するように作成されているようです。
ArrayAdapterには、mObjectsとmOriginalValuesの2つのリストがあります。mObjectsは、アダプターが機能するプライマリデータセットです。add()関数を例にとると、次のようになります。
public void add(T object) {
if (mOriginalValues != null) {
synchronized (mLock) {
mOriginalValues.add(object);
if (mNotifyOnChange) notifyDataSetChanged();
}
} else {
mObjects.add(object);
if (mNotifyOnChange) notifyDataSetChanged();
}
}
mOriginalValuesは最初はnullであるため、すべての操作(追加、挿入、削除、クリア)はデフォルトでmObjectsを対象としています。これは、リストでフィルタリングを有効にして実際に実行することを決定するまでは、すべて問題ありません。初めてフィルタリングすると、mObjectsが持つものでmOriginalValuesが初期化されます。
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<T>(mObjects);
//mOriginalValues is no longer null
}
}
if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
ArrayList<T> list = new ArrayList<T>(mOriginalValues);
results.values = list;
results.count = list.size();
}
} else {
//filtering work happens here and a new filtered set is stored in newValues
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mObjects = (List<T>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
mOriginalValuesには、元の値/アイテムのコピーが含まれるようになったため、アダプターは、事前にフィルター処理されたデータを失うことなく、mObjectsを介してフィルター処理されたリストを表示できます。
私の考えが間違っている場合は許してください(そして教えて説明してください)が、mOriginalValuesがnullでなくなったため、アダプター操作の後続のすべての呼び出しはmOriginalValuesのみを変更するため、これは奇妙だと思います。ただし、アダプターはmObjectsをプライマリデータセットとして参照するように設定されているため、何も起きていないことが画面に表示されます。それは、別のフィルタリングラウンドを実行するまでです。フィルタを削除すると、次のようになります。
if (prefix == null || prefix.length() == 0) {
synchronized (mLock) {
ArrayList<T> list = new ArrayList<T>(mOriginalValues);
results.values = list;
results.count = list.size();
}
}
最初のフィルターから変更してきたmOriginalValues(画面上では表示されていませんが)は別のリストに保存され、mObjectsにコピーされ、最終的に行われた変更が表示されます。それでも、この時点からは次のようになります。すべての操作はmOriginalValuesで実行され、変更はフィルタリング後にのみ表示されます。
解決策として、現時点で私が思いついたのは、(1)進行中のフィルタリングがあるかどうかをアダプターの操作に通知するブールフラグを設定することです。フィルタリングが完了したら、内容をコピーします。 mOriginalValuesをmObjectsに変換するか、(2)アダプターのFilterオブジェクトを呼び出し、空の文字列* .getFilter()。filter( "")を渡して、すべての操作の後にフィルターを強制します[BennySkogbergによっても提案されています]。
誰かがこの問題にもう少し光を当てるか、私が今何をしたかを確認することができれば非常にありがたいです。ありがとうございました!