onSaveInstanceState / onPause - Warten Sie, bis der Status vollständig gespeichert ist, bevor Sie zulassen, dass der Prozess beendet wird

8

Ich arbeite an meiner ersten Android App. Es verfügt über ein Modell, das in einer Datenbank beibehalten wird, wenn der Benutzer Aktualisierungen vornimmt.

Wenn onSaveInsanceState aufgerufen wird, möchte ich eine ID speichern, mit der das Dokument, an dem der Benutzer gerade gearbeitet hat, aus der Datenbank geladen werden kann. Dies kann jedoch nur passieren, wenn das Dokument die Datenbank vollständig erreicht hat. In einigen Fällen kann das Fortsetzen eines komplexen Dokuments mehrere Sekunden dauern (ich hoffe, dass dies schneller wird, wenn ich die ausführliche Abmeldung ausführe). Bei der tatsächlichen Verwendung wird vom Benutzer ein komplexes Dokument in mehreren Stufen erstellt wird in der Datenbank beibehalten, daher ist es nicht sehr wahrscheinlich, dass ein komplexes Dokument auf einmal gespeichert werden muss.)

Jetzt lautet die erste Regel für das Threading auf Android: "Blockiere den UI-Thread nicht". Die DB-Interaktionen passieren also natürlich in einem separaten Thread. Aber mein Verständnis des Android-Lebenszyklus ist, dass in vielen Fällen onSaveInstanceState aufgerufen wird, weil das Android-System den Prozess beenden möchte. Dies deutet darauf hin, dass ich diese Methode nicht zurückgeben kann, bis der DB-Thread das Speichern des Dokuments beendet hat (und tatsächlich weiß ich mit meinem aktuellen Design nicht, wie die ID-Nummer des Dokuments ist, bis es in der Datenbank gespeichert wird.) also kann ich das nicht einmal in das Bündel des gespeicherten Zustands einfügen.

Ist es unter diesen Umständen angemessen, den UI-Thread zu blockieren, der darauf wartet, dass die persistente Task ausgeführt wird? Wenn onSaveInstanceState aufgerufen wird, weil der Prozess beendet wird, ist die App nicht mehr im Vordergrund sichtbar, sodass keine Schnittstelle mehr reagiert.

Aber onSaveInstanceState wird auch aufgerufen, wenn die Activity-Instanz durch eine Konfigurationsaktualisierung zerstört wird, was geschieht, wenn sich die Bildschirmausrichtung ändert. Es ist sehr bedauerlich, wenn der Bildschirm seitlich seit einigen Sekunden nicht gedreht werden kann. In diesem Fall ist der Prozess (und damit der Speicherplatz) immer noch vorhanden, so dass ich nicht unbedingt sicherstellen muss, dass das Dokument die Datenbank trifft, wenn ich einfach einen Verweis darauf im Bundle speichern kann, anstatt dessen ID. Aber ich bin mir nicht bewusst, wie ich diese beiden Fälle unterscheiden kann.

Gibt es eine akzeptierte Praxis für diese Situationen? Sollte ich den Thread einfach blockieren, um sicher zu sein? Kann ich normale Java-Thread-Primitive einfach zum Blockieren und Warten verwenden? Gibt es etwas, was ich tun kann, dass den Thread nicht blockiert, aber sicherstellt, dass die persistente Aufgabe beendet wird, bevor Android den Prozess schließt?

All dies gilt auch für onPause , da onSaveInstanceState nicht notwendigerweise aufgerufen wird.

    
Ben 19.09.2011, 05:21
quelle

2 Antworten

2

Sie müssen nicht auf das dauerhafte Speichern in onSaveInstanceState verzichten, Sie können den Instanzstatus in Bundle speichern, so dass die Instanz in onRestoreInstanceState schnell wieder aufgenommen werden kann.

Die Dokumentation besagt, dass Sie wichtige persistente Daten (z. B. Bearbeitungen von Benutzern) in den Speicher in onPause schreiben sollten, aber es sollte auch schnell sein, damit die nächste Aktivität starten kann, was auch immer sie tun möchte .

Ich denke, meine Empfehlung wäre, den Dokumenttext und was auch immer im Bundle in onSaveInstanceState zu speichern und in onRestoreInstanceState wiederherzustellen. Verwenden Sie onPause , um eine "Sicherungskopie" irgendwo schnell zu speichern (temporäre Datei vielleicht?), Die dann in onResume wiederhergestellt werden kann, wenn sie nicht in der Datenbank gespeichert wurde. Und verwenden Sie onStop (das aufgerufen wird, wenn die Aktivität bereits im Hintergrund ist), um die Daten tatsächlich in der Datenbank zu speichern.

Beachten Sie, dass die Aktivität möglicherweise beendet wird, nachdem onPause aufgerufen wurde (nie zuvor, es sei denn, das System verfügt über sehr wenig Ressourcen ...). Deshalb würde ich eine schnelle Sicherung speichern, bevor ich versuche, sie in der Datenbank.

Bearbeiten - Extra basierend auf Kommentaren

Um sicherzustellen, dass der Hintergrund-Thread, der den Speichervorgang ausführt, gespeichert wird, bevor die Anwendung vom System beendet werden kann, denke ich, ist es in Ordnung zu blockieren und darauf zu warten, dass der Sicherungs-Thread beendet wird von onPause , aber ich empfehle, android:configChanges="orientation" zu verwenden, um den Neustart der Aktivität zu verhindern (und onPause call), wenn sich die Ausrichtung ändert.

    
Zharf 19.09.2011 06:34
quelle
0

Sie sollten versuchen, AsyncTask, die Ihr UI blockiert, aber nicht leeren Bildschirm anzeigen, wird die erforderlichen XML-Elemente laden und dann Aufruf von Async-Task, in asynchronen Task speichern Sie Ihr Dokument in der Datenbank.

Folgen Sie diesem Link: Outlook Express-Beispiel

    
mayank_droid 19.09.2011 05:59
quelle