访问关闭的游标/ AsyncTask

时间:2011-07-20 05:52:36

标签: android cursor

以下代码在我的N1上运行没有问题。但我不时会收到用户的CrashReport:

"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)

代码部分是:

    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));
}

我不知道导致这个错误的原因是什么,因为它在我的N1和模拟器中不可重复,但更重要的是我绝对不清楚为什么如果我检查Cursor.isClosed会发生这种情况

2 个答案:

答案 0 :(得分:2)

方法doInBackground始终在后台线程中运行,方法onPostExecute在UI线程上运行。

您已在后台线程范围中创建了光标的对象,当您到达onPostExecute时,后台线程可能已关闭,从而结束了光标对象的生命周期。

因此,在UI线程中创建游标对象,将游标对象的引用传递给ASyncTask。

由于这完全取决于后台线程关闭的时间,因此肯定会成为特定于设备的

答案 1 :(得分:1)

它很可能与特定方向更改的时间有关:如果在任务运行时由于方向更改导致父Activity被杀死,则光标可能会很好地关闭。