SQLite
 sql >> Datenbank >  >> RDS >> SQLite

IntentService friert die Benutzeroberfläche meiner Anwendung ein

Sind Sie sich absolut sicher, dass es sich um den IntentService handelt? das ist die Hauptursache für das Einfrieren der Benutzeroberfläche? Intent-Dienste sind speziell für die Ausführung in Worker-Threads konzipiert, um die Verarbeitung vom Hauptthread (UI) abzuladen, wobei einer der Hauptgründe dafür darin besteht, vorzubeugen Benutzeroberfläche friert ein.

Versuchen Sie vielleicht, Ihre Debugging-Bemühungen auf der UI-Ebene zu beginnen. Insbesondere was der ResultReceiver liefert zum IntentService wann Sie es starten und was Sie im onReceiveResult tun Callback-Methode in dieser Empfängerinstanz?

Abgesehen davon, überprüfen Sie für die Aktivität, bei der Sie das Einfrieren erleben, welche Art von Operationen Sie durchführen. Laden großer Datenmengen aus einer Datenbank im Haupt-Thread (d.h. ohne Verwendung eines Loader oder etwas Ähnliches, um die Verarbeitung an einen Worker-Thread auszulagern) ist eine häufige Ursache für das Einfrieren der Benutzeroberfläche, zumindest nach meiner bisherigen Erfahrung.

Aktualisieren

Ich glaube, ich habe herausgefunden, was das Problem ist. Es gibt zwei Hauptprobleme, die beide davon abhängen, wie Sie Volley verwenden. Wenn Sie der Volley-Warteschlange eine Anforderung hinzufügen, wird sie asynchron ausgeführt. Das bedeutet, dass die queue Methode kehrt sofort zurück. In Ihrem Intent-Service-Code bedeutet dies, dass der Service sofort damit fortfährt, ResultReceiver zu informieren dass es die Verarbeitung beendet hat, obwohl es eigentlich nur die Anfrage in die Warteschlange gestellt hat. Alle fünf Absichtsdienste werden dies tun, was bedeutet, dass MainActivity wird sehr schnell eingetragen. Dies ist die erste Ausgabe.

Das zweite Problem erklärt das Einfrieren, das Sie erleben. Obwohl Volley Anforderungen auf Worker-Threads ausführt, gibt es die geparsten Antworten auf Anforderungen im Haupt-Thread zurück – siehe die Dokumentation hier. Dies bedeutet, dass die gesamte Antwortverarbeitung, die Sie im Intent-Dienst durchführen (Einfügen der Daten in die Datenbank usw.), tatsächlich im Hauptthread (UI) stattfindet. Dies erklärt das Einfrieren.

Wahrscheinlich möchten Sie hier auf RequestFuture von Volley umstellen stattdessen. Dies verwandelt im Grunde eine asynchrone Anfrage in eine synchrone Anfrage, indem Sie blockieren können, bis die Anfrage abgeschlossen ist. Erstellen Sie dazu ein Future des entsprechenden Typs (JSONObject in Ihrem Fall) und legen Sie es sowohl als Listener als auch als Fehler-Listener für die Anforderung fest. Stellen Sie dann die Anfrage wie jetzt in die Warteschlange und rufen Sie unmittelbar danach get auf Methode zur Zukunft. Diese Methode wird blockiert, bis die Verarbeitung der Antwort abgeschlossen ist. Es ist in Ordnung, dies in einem Intent-Dienst zu tun, da er auf einem Worker-Thread ausgeführt wird, nicht auf dem UI-Thread.

Wenn die Anfrage erfolgreich ist, erhalten Sie die Daten zurück und Sie können die gesamte Logik ausführen, die sich derzeit in Ihrem Response.Listener befindet Implementierung. Wenn ein Fehler auftritt (d. h. die Anfrage schlägt aus irgendeinem Grund fehl), löst das Anfrage-Future eine Ausnahme aus, die Sie behandeln können, um geeignete Maßnahmen zu ergreifen.

Die Verwendung von Anfrage-Futures ist ein ganz anderer Ansatz als die Verwendung von Listenern, und Sie müssen möglicherweise Ihren Code ziemlich ändern, damit er funktioniert, aber er sollte die Probleme lösen, die Sie sehen.

Hoffe, das hilft, und ich entschuldige mich aufrichtig dafür, dass ich den Fehler nicht früher aufgegriffen habe.