2012年10月5日 星期五

Android 開發筆記 - Unable to resume activity : android.database.StaleDataException: Attempted to access a cursor after it has been closed.

以前常在操作 DBHelper 時,常常因為沒有把 mCursor.close() 而常常出現一些錯誤訊息,後來就很習慣每次取一個 mCursor 出來,用完後就執行 mCursor.close() 來當做完整的收尾,結果開始出現這種訊息並且完全不知道是自己哪一行程式出錯:


FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {com.example/com.example.YourActivity}: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2444)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2472)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1173)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:4424)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:511)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
       at dalvik.system.NativeStart.main(Native Method)
 Caused by: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
        at android.database.BulkCursorToCursorAdaptor.throwIfCursorIsClosed(BulkCursorToCursorAdaptor.java:75)
        at android.database.BulkCursorToCursorAdaptor.requery(BulkCursorToCursorAdaptor.java:144)
        at android.database.CursorWrapper.requery(CursorWrapper.java:186)
        at android.app.Activity.performRestart(Activity.java:4505)
        at android.app.ActivityThread.performRestartActivity(ActivityThread.java:2875)
        at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:168)
        at android.app.LocalActivityManager.dispatchResume(LocalActivityManager.java:523)
        at android.app.ActivityGroup.onResume(ActivityGroup.java:61)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1154)
        at android.app.Activity.performResume(Activity.java:4539)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2434)
        ... 10 more


追到最後,終於發現問題的所在點了,因為我的 mCursor 是從 Activity.managedQuery 產生的,在 Activity.managedQuery 有提到:


Warning: Do not call close() on a cursor obtained using this method, because the activity will do that for you at the appropriate time. However, if you call stopManagingCursor(Cursor) on a cursor from a managed query, the system will not automatically close the cursor and, in that case, you must call close().


這應該就是不懂 Android 架構的關係 Orz 果真懂一點不如不懂 XDD


沒有留言:

張貼留言