Соты и курсоры

#android #cursor #android-3.0-honeycomb

#Android #android-курсор #android-3.0-honeycomb

Вопрос:

У меня есть это действие, которое было полностью преобразовано для использования honeycomb. Я переработал все управление курсорами, чтобы использовать новый CursorLoader. Все отлично работает на всех других версиях ОС (с использованием библиотеки совместимости), но по-прежнему не работает на honeycomb. Следующую трассировку стека чрезвычайно сложно понять, потому что она не сообщает мне, какой курсор или какая строка терпит неудачу. Кроме того, при отладке ни одна строка кода в ParentActivity никогда не выполняется. Эта ошибка возникает, когда я возобновляю родительский доступ. Отлично работает, когда я запускаю действие, но терпит неудачу при возвращении к нему.

 05-29 17:23:32.978: ERROR/AndroidRuntime(31692): FATAL EXCEPTION: main
05-29 17:23:32.978: ERROR/AndroidRuntime(31692): java.lang.RuntimeException: Unable to resume activity {com.xxx.xxx/com.xxx.xxx.ParentActivity}: java.lang.IllegalStateException: trying to requery an already closed cursor
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2227)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2255)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1028)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.os.Looper.loop(Looper.java:132)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.ActivityThread.main(ActivityThread.java:4025)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at java.lang.reflect.Method.invokeNative(Native Method)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at java.lang.reflect.Method.invoke(Method.java:491)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at dalvik.system.NativeStart.main(Native Method)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692): Caused by: java.lang.IllegalStateException: trying to requery an already closed cursor
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.Activity.performRestart(Activity.java:4394)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.Activity.performResume(Activity.java:4420)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2217)
05-29 17:23:32.978: ERROR/AndroidRuntime(31692):     ... 10 more
  

Ответ №1:

Я столкнулся с той же проблемой. Вот что я сделал. Во всех действиях, которые я назвал startManagingCursor, я переопределяю его как:

 @Override
public void startManagingCursor(Cursor c) {

    // To solve the following error for honeycomb:
    // java.lang.RuntimeException: Unable to resume activity 
    // java.lang.IllegalStateException: trying to requery an already closed cursor
    if (Build.VERSION.SDK_INT < VersionUtil.HONEYCOMB) {
        super.startManagingCursor(c);
    }
}
  

Это позволяет моему приложению корректно работать в Honeycomb и более ранних версиях.

Комментарии:

1. Удаление startManagingCursor также устранило проблему для меня. При использовании управляемого запроса мне приходилось вызывать stopManagingCursor в honeycomb.

2. Эй, может быть, глупый вопрос, но что такое VersionUtil ? Я не могу его импортировать.

3. Это мой внутренний класс, определяющий версию honeycomb public class VersionUtil { ... public static final int HONEYCOMB = 11; ... }

Ответ №2:

У меня были те же проблемы, и я думаю, что, возможно, нашел проблему и «чистое» исправление. (Я думаю, что вообще прекращать управлять курсорами — не очень хорошая идея)

Я использую Adapter.changeCursor в некоторых действиях, которые отлично работали во всех версиях, кроме honeycomb. Метод changeCursor закрывает старый курсор, но, очевидно, не прекращает управлять этим курсором. Таким образом, activity продолжает управлять этим старым курсором, который уже закрыт. При перезапуске действия он пытается запросить его, не проверяя, закрыто ли оно.

Итак, мое решение таково:

 Cursor oldCursor = mAdapter.getCursor();
mAdapter.changeCursor(newCursor);
stopManagingCursor(oldCursor);
  

До сих пор я не могу снова воспроизвести исключение.

Комментарии:

1. Где вы это делаете, в onPause? Возможно, ваша проблема отличается от моей. Я вообще никогда не меняю курсор, но все равно получаю ошибку.

2. Я делаю это в том месте, где (когда-либо) Я изменил курсор. Возможно, ваша проблема отличается от моей.

Ответ №3:

Это результат некоторых изменений, внесенных в Honeycomb в способ управления курсорами. Ранее, если вы вызывали startManagingCursor более одного раза, все продолжало работать нормально, теперь это будет вызывать IllegalStateException , потому что действие пытается запросить закрытый курсор. Решение состоит в том, чтобы закрыть старый курсор перед повторным вызовом startManagingCursor (например, при замене курсоров).

Таким образом, ваш ParentActivity делает это косвенно в результате управляемого жизненного цикла курсора внутри Activity .

Теперь, когда вы упомянули, что используете ACL и CursorLoader, убедитесь, что вы вызываете swapCursor (курсор c) при смене курсоров, и это должно устранить ваши проблемы.

Вы можете посмотреть некоторые обсуждения этого здесь:http://groups.google.com/group/android-developers/browse_thread/thread/658133bec901d7e

Комментарии:

1. Я был несколько смущен вашим ответом, поскольку на самом деле я не меняю местами никакие курсоры, но я обнаружил, что я все еще использую startManagingCursor, и я удалил эти строки, и теперь все довольны. Я действительно ценю, что вы нашли время ответить и указали мне правильное направление. Огромное спасибо!!!

2. @Michael Little без проблем, я просто хотел охватить все свои базы, потому что это несколько способов решения одной и той же проблемы. Рад, что смог помочь

3. Лучше избавьтесь от startManagingCursor, создайте mCursor в своей деятельности. Закройте его в onPause или onDestroy (в зависимости от того, заполняете ли вы его в onResume или onCreate).