IllegalStateException - LoaderManager support using AutocompleteTextView

One of the advantages that I thought of using CursorLoaders and Loadermanagers was that you did not need to manually control the cursor life cycle. Therefore, I used the loadermanager to bind the adapter to AutoCompleteTextView using the support package.

It works quite well, except that it randomly throws the error message "IllegalStateException - attempt to reopen an already closed object." Is this really not supposed to happen if we use the bootloader manager?

Here is the code:

package com.bhagwad.tennis; import android.appwidget.AppWidgetManager; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; import android.support.v4.widget.SimpleCursorAdapter.CursorToStringConverter; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.View.OnClickListener; import android.widget.AutoCompleteTextView; import android.widget.Button; import com.bhagwad.tennis.TennisSchedule.TennisScheduleColumns; public class WidgetConfiguration extends FragmentActivity implements OnClickListener, LoaderCallbacks<Cursor> { Button mSaveWidget; AutoCompleteTextView mPlayerName; int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; String mSelection =""; SimpleCursorAdapter mAdapter; public static String PREFS = "com.bhagwad.tennis.appwidget"; public static final String PREFS_PREFIX_KEY = "prefix_"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.widget_configuration); mPlayerName = (AutoCompleteTextView) findViewById(R.id.edit_filter); mPlayerName.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (!s.equals("")) mSelection = s.toString(); else mSelection = ""; getSupportLoaderManager().restartLoader(0, null, WidgetConfiguration.this); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void afterTextChanged(Editable s) { // TODO Auto-generated method stub } }); // Set up the adapter mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, new String[] {TennisScheduleColumns.PLAYER_NAME}, new int[] {android.R.id.text1}, 0); mAdapter.setCursorToStringConverter(new CursorToStringConverter() { @Override public CharSequence convertToString(Cursor c) { return c.getString(c.getColumnIndexOrThrow(TennisScheduleColumns.PLAYER_NAME)); } }); mPlayerName.setAdapter(mAdapter); getSupportLoaderManager().initLoader(0, null, this); } @Override public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { return new CursorLoader(this, TennisScheduleColumns.CONTENT_URI_PLAYERS, new String[] {TennisScheduleColumns._ID, TennisScheduleColumns.PLAYER_NAME}, TennisScheduleColumns.PLAYER_NAME + " LIKE ?", new String[] {"%"+mSelection+"%"}, null); } @Override public void onLoaderReset(Loader<Cursor> arg0) { mAdapter.swapCursor(null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.swapCursor(data); } } 

Here's the error stack:

 08-16 22:21:23.244: E/AndroidRuntime(25475): java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT _id, player_name FROM players WHERE (player_name LIKE ?)) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:33) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:82) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:147) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:178) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.CursorWrapper.moveToPosition(CursorWrapper.java:162) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.support.v4.widget.CursorAdapter.getItem(CursorAdapter.java:213) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.buildImeCompletions(AutoCompleteTextView.java:1113) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.showDropDown(AutoCompleteTextView.java:1072) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.updateDropDownForFilter(AutoCompleteTextView.java:950) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.onFilterComplete(AutoCompleteTextView.java:932) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:285) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.os.Handler.dispatchMessage(Handler.java:99) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.os.Looper.loop(Looper.java:137) 08-16 22:21:23.244: E/AndroidRuntime(25475): at android.app.ActivityThread.main(ActivityThread.java:4507) 

Any ideas on what might be wrong?

+6
source share
1 answer

OnLoadFinished seems to sometimes trigger a call with a dead cursor - if you put the test for isClosed () on the cursor that you pass, you will find it closed in one attempt (somewhat large).

Unfortunately, the "standard" code for inclusion in OnLoadFinished immediately has changeCursor () on the adapter, and as it follows, this is chaos, stackdumps, pestilence, etc.

My solution is no more beautiful than your try / catch. ignore the dummy OnLoadFinished and risk that the end user gets an empty user interface.

+7
source

Source: https://habr.com/ru/post/923091/


All Articles