Weet je absoluut zeker dat het de IntentService
. is? dat is de oorzaak van het bevriezen van de gebruikersinterface? Intent-services zijn speciaal ontworpen om in werkthreads te worden uitgevoerd om de verwerking van de hoofdthread (UI) te ontlasten, met als een van de belangrijkste redenen om te helpen voorkomen UI loopt vast.
Misschien kunt u proberen uw debugging-inspanningen op UI-niveau te starten. In het bijzonder, wat levert de ResultReceiver
naar de IntentService
wanneer u het start, en wat doet u in de onReceiveResult
callback-methode in die ontvangerinstantie?
Anders dan dat, controleer voor de activiteit waarin u de bevriezing ervaart, wat voor soort bewerkingen u uitvoert. Het laden van grote hoeveelheden gegevens uit een database op de hoofdthread (d.w.z. zonder gebruik van een Loader
of iets dat lijkt op het offloaden van de verwerking naar een werkthread) is een veelvoorkomende oorzaak van het vastlopen van de gebruikersinterface, althans in mijn ervaring tot nu toe.
Bijwerken
Ik denk dat ik erachter ben wat het probleem is. Er zijn twee hoofdproblemen, die beide voortkomen uit de manier waarop je Volley gebruikt. Wanneer u een aanvraag toevoegt aan de Volley-wachtrij, wordt deze asynchroon uitgevoerd. Dat betekent dat de queue
methode keert onmiddellijk terug. In uw intentie-servicecode betekent dit dat de service onmiddellijk doorgaat met het doorgeven van de ResultReceiver
dat het klaar is met verwerken, terwijl het eigenlijk alleen maar het verzoek in de wachtrij heeft gezet. Alle vijf de intentieservices zullen dit doen, wat betekent dat MainActivity
zeer snel zal worden ingevoerd. Dit is het eerste nummer.
Het tweede probleem verklaart de bevriezing die u ervaart. Hoewel Volley verzoeken uitvoert op werkthreads, retourneert het de geparseerde antwoorden op verzoeken op de hoofdthread - zie de documentatie hier. Dit betekent dat alle responsverwerking die u doet in de intentieservice (het plaatsen van de gegevens in de database, enz.) daadwerkelijk plaatsvindt op de hoofdthread (UI). Dit verklaart het bevriezen.
Wat je hier waarschijnlijk wilt doen, is overschakelen naar het gebruik van Volley's RequestFuture
in plaats van. Dit verandert in feite een asynchrone aanvraag in een synchrone door u toe te staan te blokkeren totdat de aanvraag is voltooid. Maak hiervoor een toekomst van het juiste type (JSONObject
in uw geval) en stel het in als zowel de listener als de foutlistener voor het verzoek. Zet het verzoek dan in de wachtrij zoals u nu doet, en bel onmiddellijk daarna de get
methode voor de toekomst. Deze methode blokkeert totdat het antwoord is verwerkt. Het is prima om dit in een intent-service te doen, omdat deze wordt uitgevoerd op een werkthread, niet op de UI-thread.
Als het verzoek slaagt, krijgt u de gegevens terug en kunt u alle logica uitvoeren die momenteel in uw Response.Listener
staat. implementatie. Als er een fout optreedt (d.w.z. het verzoek mislukt om de een of andere reden), zal het toekomstige verzoek een uitzondering genereren die u kunt afhandelen om de juiste acties te ondernemen.
Het gebruik van request futures is een heel andere benadering van het gebruik van listeners en het kan zijn dat je je code behoorlijk moet veranderen om het te laten werken, maar het zou de problemen moeten oplossen die je ziet.
Ik hoop dat dat helpt, en mijn oprechte excuses dat ik de bug niet eerder heb opgepikt.