This is my first time testing out SimpleCursorAdapter. I want to use it with ORMLite.
Unfortunately, I always get StaleDataException :(
EDIT: not sure anymore if adapter.swapCursor(c) is the problem. stepped over that without problems. the problem seems to be somewhere else /END EDIT
The error seems to occur in adapter.swapCursor(c). c is closed, this seems to be the problem, how can I fix that and why exactly is it closed? Note: the error ONLY occurs if the Einsatz1 sqllite table contains data. Everything runs perfectly if the table is empty.
This is my activity:
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);
}
}
This is my 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)
Small note (unimportant, but if someone has info...): When I set breakpoint before adapter.swapCursor(c), it does not stop there before throwing the error. I have to set a breakpoint to do a dummy "int bla = 123" inserted before that statement. Similarly, setting a breakpoint anywhere in public Cursor query(...) method makes everything execute without errors (what the hell...), but again not stopping at the breakpoint.
yep it looks like it's due to iterator.closeQuietly(), though the affect of commenting that out is you might now have a leak with many iterators opened (which should really be closed).
Instead, in your onQuery() method, try using the following which will give you a reference to the Cursor, which should close when your ContentProvider is closed.