Java: ORMLite с SimpleCursorAdapter: StaleDataException
Я впервые тестирую SimpleCursorAdapter. Я хочу использовать его с ORMLite.
К сожалению, я всегда получаю StaleDataException:(
РЕДАКТИРОВАТЬ:больше не уверен, если проблема заключается в файле adapter.swapCursor(c). перешагнул через это без проблем. проблема, кажется, где-то еще /END EDIT
Кажется, ошибка возникает в файле adapter.swapCursor(c). с закрыт, кажется, это проблема, как я могу это исправить и почему именно он закрыт? Примечание: ошибка возникает ТОЛЬКО, если таблица sqlite Einsatz1 содержит данные. Все работает отлично, если таблица пуста.
Это моя деятельность:
public class UebersichtEinsaetze extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor>
{
...
public DatabaseHelper helper = null;
@Override
protected void onDestroy()
{
super.onDestroy();
((SimpleCursorAdapter) einsatzListView.getAdapter()).getCursor().close();
helper.close();
if (helper != null)
{
OpenHelperManager.releaseHelper();
helper = null;
}
}
private DatabaseHelper getHelper()
{
if (helper == null)
{
helper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
}
return helper;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ubersicht_einsaetze);
einsatzListView = (ListView) findViewById(android.R.id.list);
einsatzDatumTextView = (TextView) findViewById(R.id.tv_uebersicht_abdatum);
fillData();
getHelper();
}
private void fillData()
{
String[] from = new String[] { "_id" };
int[] to = new int[] { R.id.view_list_einsatz_text_projnr };
adapter = new SimpleCursorAdapter(this, R.layout.view_list_eintrag_einsatz, null, from, to, 0);
getSupportLoaderManager().initLoader(0, null, this);
einsatzListView.setAdapter(adapter);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
String[] projection = { "_id" };
CursorLoader cursorLoader = new CursorLoader(this, test.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c)
{
adapter.swapCursor(c);
}
@Override
public void onLoaderReset(Loader<Cursor> loader)
{
adapter.swapCursor(null);
}
}
Это мой Contentprovider:
private DatabaseHelper database;
private RuntimeExceptionDao<Einsatz1, String> dao;
// Used for the UriMacher
private static final int EINSAETZE = 10;
private static final int EINSATZ_ID = 20;
private static final String AUTHORITY = "de.myapp.android";
private static String BASE_PATH = "einsaetze";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/einsaetze";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/einsatz";
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static
{
sURIMatcher.addURI(AUTHORITY, BASE_PATH, EINSAETZE);
sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", EINSATZ_ID);
}
@Override
public boolean onCreate()
{
database = new DatabaseHelper(getContext());
this.dao = (RuntimeExceptionDao<Einsatz1, String>) database.getRTE(Einsatz1.class);
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
{
// ignore method parameters for now just to get it basically working
QueryBuilder<Einsatz1, String> queryBuilder = this.dao.queryBuilder();
Cursor cursor = null;
CloseableIterator<Einsatz1> iterator = null;
try
{
iterator = dao.iterator(queryBuilder.prepare());
AndroidDatabaseResults results = (AndroidDatabaseResults) iterator.getRawResults();
cursor = results.getRawCursor();
}
catch (SQLException e)
{
Log.e(getClass().getName(), "get cursor", e);
}
finally
{
iterator.closeQuietly();
}
// Make sure that potential listeners are getting notified
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
Logcat:
01-09 10:01:29.591: E/AndroidRuntime(3767): FATAL EXCEPTION: main
01-09 10:01:29.591: E/AndroidRuntime(3767): android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method.
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:139)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.database.CursorWrapper.getString(CursorWrapper.java:114)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.support.v4.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:135)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.support.v4.widget.CursorAdapter.getView(CursorAdapter.java:256)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.AbsListView.obtainView(AbsListView.java:2267)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.ListView.measureHeightOfChildren(ListView.java:1244)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.ListView.onMeasure(ListView.java:1156)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.RelativeLayout.measureChild(RelativeLayout.java:602)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:415)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-09 10:01:29.591: E/AndroidRuntime(3767): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.View.measure(View.java:15172)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.Choreographer.doCallbacks(Choreographer.java:555)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.Choreographer.doFrame(Choreographer.java:525)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.os.Handler.handleCallback(Handler.java:615)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.os.Handler.dispatchMessage(Handler.java:92)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.os.Looper.loop(Looper.java:137)
01-09 10:01:29.591: E/AndroidRuntime(3767): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-09 10:01:29.591: E/AndroidRuntime(3767): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 10:01:29.591: E/AndroidRuntime(3767): at java.lang.reflect.Method.invoke(Method.java:511)
01-09 10:01:29.591: E/AndroidRuntime(3767): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-09 10:01:29.591: E/AndroidRuntime(3767): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-09 10:01:29.591: E/AndroidRuntime(3767): at dalvik.system.NativeStart.main(Native Method)
Небольшое примечание (неважно, но если у кого-то есть информация...): Когда я устанавливаю точку останова перед adapter.swapCursor(c), она не останавливается там до выдачи ошибки. Я должен установить точку останова, чтобы сделать фиктивный "int bla = 123", вставленный перед этим оператором. Точно так же установка точки останова в любом месте в публичном методе запроса Cursor (...) заставляет все выполняться без ошибок (какого черта...), но опять же не останавливаясь в точке останова.
2 ответа
РЕШИТЬ
Закомментируйте
iterator.closeQuietly();
Хотя я нашел код, который пришел отсюда:
Курсор Android с ORMLite для использования в CursorAdapter
... не стоит полагаться на это.
Мне нужно посмотреть, какие потенциальные негативные последствия будет иметь комментирование (если кто-то знает, пожалуйста, скажите мне), но сейчас все работает.
Да, похоже, это происходит из-за iterator.closeQuietly(), хотя эффект от комментирования это может привести к утечке с множеством открытых итераторов (которые действительно должны быть закрыты).
Вместо этого в вашем методе onQuery() попробуйте использовать следующее, которое даст вам ссылку на курсор, который должен закрываться при закрытии вашего ContentProvider.
Cursor cursor = getHelper().getReadableDatabase().query(tableName, projection, selection, selectionArgs, groupBy, having, sortOrder)