2 Stimmen

Widget-Update führt zu ANR

Ich habe eine einfache App, die Internetressourcen liest und die Informationen in einem Widget oder in einer Listenansicht in Form von ImageViews und TextViews anzeigt. Neben dem Herunterladen der Daten aus dem Internet zeigt es diese auch in einem Widget in einem ViewFlipper an.

Wenn ich das Widget dem Startbildschirm hinzufüge, wird onUpdate sofort aufgerufen, lädt die Daten aus dem Internet herunter und aktualisiert das Widget. Das funktioniert einwandfrei. Das Log zeigt onUpdate und dataDownloaded mit etwa 3 Sekunden Abstand. Beim nächsten Update (wenn das Telefon im Schlafmodus ist), erfolgt das Update nicht und das zeigen meine Logs an.

  • onUpdate wird aufgerufen.
  • dataDownloading wird aufgerufen, aber erst nach 20 Sekunden nachdem onUpdate initial aufgerufen wurde. Ich nehme an, dass dies daran liegt, dass das Telefon im Schlafmodus ist und Zeit benötigt, um Netzwerksockets usw. zu initialisieren.
  • Danach erhalte ich den ANR-Logeintrag und das Widget-Update erfolgt nicht, der Prozess ist praktisch blockiert, das Widget bleibt auf dem Bildschirm und reagiert nicht auf manuelle Updates von innerhalb der Aktivität, was sonst funktioniert, wenn keine ANR-Ausnahme geworfen wird.

Ich suche nach einer möglichen Lösung dafür. Ich dachte daran, alle Downloads in einem anderen Thread (von innerhalb des AppWidgetProvider, möglicherweise mit AsyncTask) durchzuführen, die Daten in SQLite oder im lokalen Speicher zu speichern und das Widget-Update (keine Downloads, nur das Lesen der Daten aus SQLite und dem lokalen Speicher) beim nächsten onUpdate-Aufruf durchzuführen. Damit würde der Anwendungs-/Widget-Prozess reaktionsfähiger werden und nicht in einen ANR-Fehler geraten.

Ist dieser Ansatz mit Threads eine schlechte Praxis? Gibt es eine Alternative? Sollte ich stattdessen einen Service verwenden? Ich neige dazu, keinen Service zu verwenden, es sei denn, es gibt viele Vorteile dafür.

Entschuldigung für die Textwand :)

Bearbeiten: Aus den Dokumenten http://developer.android.com/guide/practices/design/responsiveness.html

Android zeigt den ANR-Dialog für eine bestimmte Anwendung an, wenn es eine der folgenden Bedingungen feststellt:

  • Keine Antwort auf ein Eingabebegnissen (z. B. Tastendruck, Bildschirmtouch) innerhalb von 5 Sekunden
  • Ein BroadcastReceiver hat die Ausführung nicht innerhalb von 10 Sekunden abgeschlossen

2voto

Graham Borland Punkte 58864

Das Verknüpfen ist die einzige Möglichkeit, um sicher auf Android auf das Netzwerk zuzugreifen. Also ja, du wirst etwas wie eine ASyncTask oder IntentService verwenden müssen. Beachte, dass ein einfacher Service nicht viel helfen wird, da dieser im Hauptthread ausgeführt wird.

2voto

dave.c Punkte 10907

Wenn Sie eine Netzwerkanforderung durchführen, müssen Sie dies entweder innerhalb eines AsyncTask oder in einer Kombination aus Thread/Handler tun. Hier sind einige Links, die Ihnen helfen sollen:

2voto

ramdroid Punkte 6598

Die Verwendung von IntentService und einer Datenbank als Backend ist wohl der richtige Weg, um es zu tun, denke ich.

Was man jedoch niemals tun sollte, ist solche Hintergrundaufgaben auszuführen, wenn die Anwendung nicht aktiv ist. Bitte lade Daten nur herunter, wenn deine App im Vordergrund ist!

Was das Widget betrifft, solltest du das Attribut "updatePeriodMillis" verwenden. Das Android-System stellt sicher, dass dies nur ausgeführt wird, wenn das Widget sichtbar ist.

Für weitere Hinweise schau an der üblichen Stelle nach:

http://developer.android.com/guide/topics/appwidgets/index.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X