Android-Fehler: java.lang.IllegalStateException: Es wird versucht, einen bereits geschlossenen Cursor erneut abzufragen
Umgebung (Linux - /Eclipse-Dev für das Xoom-Tablet mit HoneyComb 3.0.1)
In meiner app bin ich mit der Kamera (startIntentForResult()) ein Bild zu machen. Nach der Aufnahme bekomme ich die onActivityResult() callback und bin laden können Sie eine Bitmap mit einer Uri übergeben, die über die "Bild" - Vorsatz. An diesem Punkt meiner Tätigkeit wieder aufgenommen wird und ich bekomme eine Fehlermeldung, die versuchen, um neu zu laden der Bilder in einer Galerie:
FATAL EXCEPTION: main
ERROR/AndroidRuntime(4148): java.lang.RuntimeException: Unable to resume activity {...}:
java.lang.IllegalStateException: trying to requery an already closed cursor
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2243)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1019)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:126)
at android.app.ActivityThread.main(ActivityThread.java:3997)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: trying to requery an already closed cursor
at android.app.Activity.performRestart(Activity.java:4337)
at android.app.Activity.performResume(Activity.java:4360)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2205)
... 10 more
Nur die cursor-Logik, die ich verwende, ist, dass, nachdem das Bild aufgenommen ich umwandeln der Uri zu einer Datei mit der folgenden Logik
String [] projection = {
MediaStore.Images.Media._ID,
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.Media.DATA
};
Cursor cursor = activity.managedQuery(
uri,
projection, //Which columns to return
null, //WHERE clause; which rows to return (all rows)
null, //WHERE clause selection arguments (none)
null); //Order-by clause (ascending by name)
int fileColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
return new File(cursor.getString(fileColumnIndex));
}
return null;
Irgendwelche Ideen was ich falsch mache?
InformationsquelleAutor der Frage cyber-monk | 2011-05-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sieht aus wie die managedQuery () - Aufruf ist veraltet in der Wabe-API.
Doc für managedQuery() liest:
Außerdem bemerkte ich, dass ich aufrufen cursor.close() nach der Abfrage, die ich Schätze, ist ein no-no. Fand diese wirklich nützlicher link als gut. Nach etwas Lektüre kam ich mit dieser änderung, die zu funktionieren scheint.
InformationsquelleAutor der Antwort cyber-monk
Für das Protokoll, hier ist, wie ich fest das in meinem code (der läuft auf Android 1.6 und aufwärts): Das problem in meinem Fall war, dass ich versehentlich schließen managed Cursor durch den Aufruf CursorAdapter.changeCursor(). Aufruf-Aktivität.stopManagingCursor() auf die adapter-cursor ändern, bevor der cursor das problem gelöst:
InformationsquelleAutor der Antwort Martin Stone
FIX: verwenden Sie
context.getContentResolver().query
stattactivity.managedQuery
.InformationsquelleAutor der Antwort Vincent Czz
Habe ich diese Frage hier, da konnte ich nicht kommentieren, die Letzte Antwort (Kommentare deaktiviert aus irgendeinem Grund). Ich dachte, die Eröffnung eines neuen thread auf, das wird nur die Dinge zu komplizieren.
Bekomme ich die Anwendung stürzt ab, wenn ich gehe von Aktivität Eine zu Aktivität B und dann zurück zu Aktivität Eine. Dies passiert aber nicht ständig - nur manchmal und ich habe harte Zeit der Suche, wo GENAU dies geschieht. All das geschieht auf dem gleichen Gerät (Nexus S), aber ich glaube nicht, dass das ein Geräte-Problem.
Ich habe einige Fragen bezüglich @Martin Stine Antwort.
changeCursor(c);
: "Ändern Sie die zugrunde liegenden Cursors um einen neuen cursor. Wenn es eine vorhandene cursor wird geschlossen werden". Also warum muss ichstopManagingCursor(currentCursor);
- ist das nicht redundant?((SimpleCursorAdapter)getListAdapter())
bewerten zu NULL, weil kein cursor war noch zu schaffen. Sicher, ich könnte prüfen, ob ich NICHT bekommen, eine null und erst dann versuchen, zu stoppen, um verwalten Sie den cursor, aber schließlich habe ich beschlossen, meine " stopManagingCursor(currentCursor); in der onPause () - Methode dieser Tätigkeit. Ich dachte, auf diese Weise werde ich sicher einen cursor zu stoppen, zu verwalten und ich sollte es tun, kurz bevor ich verlassen die Aktivität zu einem anderen. Das Problem - ich bin mit mehreren Cursorn (eins-zu-füllen mit einem text von EditText-Feld und die andere für eine Listenansicht) in meine Tätigkeit, die ich denke, nicht alle von Ihnen sind mit einem ListAdapter cursor -onPause()
?So viele Fragen... Hoffe, dass jemand helfen könnte.
Wenn ich
onPause()
ich habe einen cursor zu stoppen, zu verwalten, aber ich bin noch zu bestimmen, ob dies das problem löst, da dieser Fehler zeigt sich nur sporadisch.Vielen Dank!
NACH EINIGEN UNTERSUCHUNGEN:
Fand ich etwas Interessantes, dass vielleicht die Antwort geben auf die "geheimnisvolle" Seite dieser Ausgabe:
Aktivität Eine verwendet zwei Cursor: ein zu füllen ein EditText-Feld. Der andere ist zum füllen eines ListView.
Beim Wechsel von Aktivität A zu Aktivität B und wieder zurück kommen, wird das Feld + ListView in Aktivität A muss wieder gefüllt. Es scheint, wie das EditText Feld wird nie ein Problem haben. Ich konnte nicht finden einen Weg, um das EditText-Feld der cursor (wie in
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
) und die Vernunft sagt mir, dass das EditText-Feld nicht halten. Auf der anderen Seite das ListView - "erinnert" Sie sich Ihr cursor vom letzten mal (von vor der Aktivität Ein -> Aktivität B). Darüber hinaus, und dies ist eine seltsame Sache, dieCursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
wird eine andere ID nach Aktivität B -> Aktivität Ein und alle diese OHNE mich immer anrufenIch denke, in einigen Fällen, wenn das system benötigt, um Ressourcen freizugeben, der cursor wird getötet werden, und sobald eine Aktivität B -> Aktivität Ein, das system wird weiterhin versuchen, mit dieser alten, abgestorbenen cursor, die zu einer Ausnahme führen. Und in anderen Fällen das system wird sich mit einem neuen cursor, der ist noch am Leben und somit keine Ausnahme auftreten. Das könnte auch erklären, warum dieser zeigt sich nur manchmal. Ich denke, das ist schwer zu Debuggen, aufgrund des Unterschieds der Anwendung Geschwindigkeit, wenn Sie entweder ausführen ODER Debuggen der Anwendung. Beim Debuggen, es braucht mehr Zeit, und so geben Sie dem system Zeit, um sich mit einem neuen cursor, oder Umgekehrt.
In meinem Verständnis das macht die Verwendung von
Als empfohlen von @Martin Stine ein muss in EINIGEN Fällen und redundante in ANDEREN: wenn ich zurück in die Methode und das system versucht, mit einem Toten cursor, muss man erstellen Sie einen neuen cursor und ersetzen Sie es in der ListAdapter, sonst werde ich wütend app-Nutzer mit einer app abgestürzt. In einem anderen Fall, wenn das system wird sich selbst eine neue cursor - die Zeilen oben sind redundant, da Sie ungültig, eine gute cursor-und eine neue erstellen.
Ich denke, um zu verhindern, dass diese Redundanz die ich brauchen würde, so etwas wie dieses:
Ich würde gerne hören, was Sie darüber denken!
InformationsquelleAutor der Antwort roysch
Fügen Sie einfach den folgenden code an das Ende der cursor-block..
InformationsquelleAutor der Antwort Exceptional
Dieses problem plagte mich für eine lange Zeit und ich endlich eine einfache Lösung, die funktioniert wie ein Charme auf allen Versionen von Android. Erste, nicht verwenden startManagingCursor (), da Sie offensichtlich fehlerhaft und veraltet in jedem Fall. Zweitens, schließen Sie einen Cursor so schnell wie möglich, nachdem Sie fertig sind mit ihm. Ich verwenden versuchen, und schließlich, um sicherzustellen, dass der Cursor geschlossen wird, unter allen Umständen. Wenn deine Methode zurückgeben muss eine Cursor dann zu der aufrufenden routine ist verantwortlich für das schließen Sie es so bald wie möglich.
Ich verwendet, um zu verlassen Cursor öffnen, für die Lebensdauer einer Aktivität, aber ich habe da aufgegeben, dass für diese transaktionale Ansatz. Nun meine app ist sehr stabil und leidet nicht unter "Android error: java.lang.IllegalStateException: requery versucht, einen bereits geschlossenen cursor" beim Umschalten Aktivitäten, obwohl Sie Zugriff auf die gleiche Datenbank.
InformationsquelleAutor der Antwort cdavidyoung