AutoCompleteTextView с CursorLoader и SimpleCursorAdapter

Я пытаюсь заполнить список предложений данными db. Однако я получаю StaleDataException s. Он выбрасывается довольно случайным образом, но всегда, когда я ввожу персонажа в текстовое окно.

Вот мой код:

CursorLoader расширяет класс Cristian 's SimpleCursorLoader

 public class TagCursorLoader extends SimpleCursorLoader { private String mSelection; private TagDbLoader mDbLoader; public TagCursorLoader(Context context, TagDbLoader dBLoader, String selection) { super(context); this.mDbLoader = dBLoader; this.mSelection = selection; } @Override public Cursor loadInBackground() { return mDbLoader.fetchContainingString(mSelection); } } 

Обратные вызовы Loader:

 public class TagCursorLoaderCallback implements LoaderCallbacks<Cursor>, CursorToStringConverter { private Context mContext; private TagDbLoader mdDbLoader; private SimpleCursorAdapter mAdapter; private String mSelection; public TagCursorLoaderCallback(Context context, TagDbLoader dBLoader, SimpleCursorAdapter adapter) { this.mContext = context; this.mdDbLoader = dBLoader; mAdapter = adapter; mSelection = ""; } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new TagCursorLoader(mContext, mdDbLoader, mSelection); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { if (!data.isClosed()) { mAdapter.swapCursor(data); } } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } public void setSelection(String mSelection) { this.mSelection = mSelection; } @Override public CharSequence convertToString(Cursor cursor) { return cursor.getString(cursor.getColumnIndexOrThrow(DbConstants.Tags.KEY_TAG)); } } 

И, наконец, когда я настроил AutoCompleteTextView :

 private void initializeAutoComplete() { mTagDbLoader = new TagDbLoader(getActivity()); mTagDbLoader.open(); mTagInput = (AutoCompleteTextView) mLayout.findViewById(R.id.autoComplete); mTagInput.addTextChangedListener(new TextWatcherAdapter() { @Override public void afterTextChanged(Editable s) { mLoaderCallback.setSelection(s.toString()); getLoaderManager().restartLoader(0, null, mLoaderCallback); } }); mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, null, new String[] { DbConstants.Tags.KEY_TAG }, new int[] { android.R.id.text1 }, 0); mLoaderCallback = new TagCursorLoaderCallback(getActivity(), mTagDbLoader, mAdapter); mAdapter.setCursorToStringConverter(mLoaderCallback); mTagInput.setAdapter(mAdapter); getLoaderManager().initLoader(0, null, mLoaderCallback); } 

После некоторого расследования кажется, что SimpleCursorAdapter наследуется от ResourceCursorAdapter , который наследуется от CursorAdapter . CursorAdapter использует CursorFilter для фильтрации, и этот класс вызывает changeCursor() в своем publishResults() . changeCursor закрывает старый курсор … Вот почему мои курсоры были закрыты автоматически.

Я сбросил загрузчики и изменил реализацию на код ниже, и он очень сильно работает:

 mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, mTagDbLoader.fetchAll(), new String[] { DbConstants.Tags.KEY_TAG }, new int[] { android.R.id.text1 }, 0); mAdapter.setFilterQueryProvider(new FilterQueryProvider() { @Override public Cursor runQuery(CharSequence constraint) { if (constraint == null || constraint.equals("")) return mAdapter.getCursor(); return mTagDbLoader.fetchContainingString(constraint.toString()); } }); mAdapter.setCursorToStringConverter(new CursorToStringConverter() { @Override public CharSequence convertToString(Cursor c) { return c.getString(c.getColumnIndexOrThrow(DbConstants.Tags.KEY_TAG)); } });