the following code works without problems on my N1. But from time to time I get a CrashReport from my users:
"android.database.StaleDataException: Access closed cursor
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:217)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
at android.database.CursorWrapper.getString(CursorWrapper.java:135)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.setRelationInfo(PartnerZodiacsView.java:456)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.setReleationInfoAfterPostExecute(PartnerZodiacsView.java:449)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView.access$10(PartnerZodiacsView.java:447)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView$5.onPostExecute(PartnerZodiacsView.java:440)
at at.mikemitterer.android.partnerzodiacs.PartnerZodiacsView$5.onPostExecute(PartnerZodiacsView.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:417)
at android.os.AsyncTask.access$300(AsyncTask.java:127)
The code-part is:
public void updateRelationInfoAsync() {
new AsyncTask<Void, Void, Void>() {
private Cursor cursorRelation = null;
@Override
protected Void doInBackground(final Void... voids) {
try {
cursorRelation = ProviderQueries.getInstance().getRelationByID(PartnerZodiacsView.this, firstRelationUID, secondRelationUID);
}
catch (final RelationNotSetException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(final Void result) {
super.onPostExecute(result);
setReleationInfoAfterPostExecute(cursorRelation);
cursorRelation = null;
}
}.execute();
}
private synchronized void setReleationInfoAfterPostExecute(final Cursor cursorRelation) {
if (cursorRelation != null && (!cursorRelation.isClosed())) {
setRelationInfo(cursorRelation);
setRatings(cursorRelation);
cursorRelation.close();
}
}
private void setRelationInfo(final Cursor cursor) {
maininfo.setText(cursor.getString(cursor.getColumnIndex(RelationDAO.Colums.DESCRIPTION)));
final String name = cursor.getString(cursor.getColumnIndex(RelationDAO.Colums.RELATIONNAME));
AnalyticsUtils.getInstance(this).trackPageView("/relationdisplayed?name=" + URLEncoder.encode(name));
}
I don’t know what causes this error, as said it’s not reproducible on my N1 and in the emulator but the more important thing is that it’s absolutely unclear to me why this can happen if I check for Cursor.isClosed
The method
doInBackgroundalways runs in the background thread and the methodonPostExecuteruns on the UI Thread.You have created the object of the cursor in the background thread scope and by the time you reach the
onPostExecutethe background thread might have been closed thus ending the lifetime of the cursor object.So, create the cursor object in your UI thread a pass a reference of the cursor object to your ASyncTask.
Since this completely depends on the timing of the closure of the background thread it is definitely becomes device specific