Volley is een netwerkbibliotheek die is ontwikkeld door Google en is geïntroduceerd tijdens Google I / O 2013. Deze bibliotheek is ontwikkeld vanwege de afwezigheid in de Android SDK van een netwerkklasse die kan werken zonder de gebruikerservaring te verstoren..
Tot de release van Volley, de canonieke Java-klasse java.net.HttpURLConnection
en de Apache org.apache.http.client
waren de enige tools die beschikbaar waren voor Android-programmeurs om een RESTful-systeem te ontwikkelen tussen een client en een externe backend.
Afgezien van het feit dat deze twee klassen niet zijn vrijgesteld van bugs, moet worden opgemerkt hoe alles dat verder ging dan een eenvoudige HTTP-transactie ex novo moest worden geschreven. Als u afbeeldingen in de cache wilt opslaan of verzoeken wilt prioriteren, moet u deze helemaal zelf ontwikkelen.
Gelukkig is er nu Volley, gemaakt en op maat gemaakt om aan deze behoeften te voldoen.
HttpURLConnection
en HttpClient
Op lagere API-niveaus (meestal op Gingerbread en Froyo), HttpURLConnection
en HttpClient
zijn verre van perfect. Er zijn enkele bekende problemen en bugs die nooit zijn opgelost. Bovendien, HttpClient
is verouderd in de laatste API-update (API 22), wat betekent dat deze niet langer wordt onderhouden en mogelijk wordt verwijderd in een toekomstige release.
Dit zijn voldoende redenen om te besluiten om over te schakelen naar een betrouwbaarder manier om uw netwerkverzoeken af te handelen.
AsyncTask
TeSinds de introductie van Honeycomb (API 11) is het verplicht om netwerkbewerkingen uit te voeren op een afzonderlijke thread, anders dan de hoofdthread. Deze substantiële verandering leidde de weg naar massaal gebruik van de AsyncTask
specificatie.
Met AsyncTask
, u definieert eerst enkele voorbereidende acties, zoals de definitie van de context, in onPreExecute
. Vervolgens voert u uw asynchrone taken uit met behulp van de doInBackground
methode. Tot slot verwerkt u de resultaten onPostExecute
. Het is vrij eenvoudig, veel eenvoudiger dan de implementatie van een service en wordt geleverd met een massa voorbeelden en documentatie.
Het grootste probleem is echter de serialisatie van de oproepen. De ... gebruiken AsyncTask
klas, je kunt niet beslissen welk verzoek het eerst wordt gedaan en welke moet wachten. Alles gebeurt FIFO, als eerste in, als eerste.
De problemen ontstaan bijvoorbeeld wanneer u een lijst met items moet laden die een miniatuur hebben bijgevoegd. Wanneer de gebruiker naar beneden scrolt en nieuwe resultaten verwacht, kunt u uw activiteit niet vertellen om eerst de JSON van de volgende pagina te laden en alleen dan de afbeeldingen van de vorige. Dit kan een serieus probleem met de gebruikerservaring worden in toepassingen zoals Facebook of Twitter, waar de lijst met nieuwe items belangrijker is dan de bijbehorende thumbnail..
Volley probeert dit probleem op te lossen door een krachtige annulerings-API op te nemen. U hoeft niet langer in te checken onPostExecute
of de activiteit tijdens het uitvoeren van de oproep werd vernietigd. Dit helpt ongewenst gedrag te voorkomen NullPointerException
.
Enige tijd geleden deed het Google+ team een reeks prestatietests op elk van de verschillende methoden die u kunt gebruiken om netwerkverzoeken op Android te maken. Volley kreeg een score die tot tien keer beter was dan de andere alternatieven bij gebruik in REST-toepassingen.
Volley slaat verzoeken automatisch caches op en dit is echt levensreddend. Laten we even teruggaan naar het voorbeeld dat ik eerder gaf. U hebt een lijst met items - laten we zeggen een JSON-matrix - en elk item heeft een beschrijving en een bijbehorende miniatuur. Bedenk nu wat er gebeurt als de gebruiker het scherm draait: de activiteit wordt vernietigd, de lijst wordt opnieuw gedownload en de afbeeldingen ook. Lang verhaal kort, een aanzienlijke verspilling van middelen en een slechte gebruikerservaring.
Volley blijkt buitengewoon handig te zijn om dit probleem op te lossen. Het onthoudt de vorige oproepen deed het en behandelt de vernietiging en reconstructie van activiteiten. Het caches alles zonder dat je je zorgen hoeft te maken.
Volley is perfectvoor kleine oproepen, zoals JSON-objecten, delen van lijsten, details van een geselecteerd item, enzovoort. Het is ontworpen voor REST-toepassingen en in dit specifieke geval geeft het zijn uiterste best.
Het is echter niet zo goed als het wordt gebruikt voor streaming-operaties en grote downloads. In tegenstelling tot wat vaak wordt gedacht, komt de naam van Volley niet van het sportwoordenboek. Het is eerder bedoeld als herhaalde bursts van oproepen, gegroepeerd. Het is op een of andere manier intuïtief waarom deze bibliotheek niet van pas komt als je in plaats van een salvo van pijlen een kanonskogel wilt afvuren.
Volley werkt op drie verschillende niveaus waarbij elk niveau op zijn eigen draad werkt.
Op de rode draad, consistent met wat je al doet in de AsyncTask
specificatie, mag u alleen het verzoek indienen en het antwoord afhandelen. Niets meer niets minder.
Het belangrijkste gevolg is dat je eigenlijk alles kunt negeren wat er gaande was in de doInBackground
methode. Volley beheert automatisch de HTTP-transacties en de vangnetmeldingen die u eerder nodig had.
Wanneer u een verzoek aan de wachtrij toevoegt, gebeuren er verschillende dingen onder de motorkap. Ten eerste controleert Volley of het verzoek vanuit de cache kan worden hersteld. Als dit het geval is, wordt het in de cache opgeslagen antwoord gelezen, geparseerd en afgeleverd. Anders wordt het doorgegeven aan de netwerkthread.
Op de netwerkdraad werkt een round-robin met een reeks threads constant. De eerste beschikbare netwerkdraad haalt de aanvraag op, maakt de HTTP-aanvraag, parseert de reactie en schrijft deze naar de cache. Om te eindigen, verzendt het de geparseerde reactie terug naar de rode draad waar uw luisteraars wachten om het resultaat af te handelen.
Volley is niet zo handig om op te zetten. Het lijkt erop dat er geen officiële Maven-repository beschikbaar is en dat is nogal verbijsterend. U moet vertrouwen op de officiële broncode. U kunt Volley op verschillende manieren importeren.
Begin eerst met het downloaden van de Volley-bron uit de repository. Als je er vertrouwen in hebt om dit te doen, deze Gitcommando kan al het werk voor u doen:
git clone https://android.googlesource.com/platform/frameworks/volley
Tot een paar weken geleden kon je alles inpakken met behulp van de mier opdrachtregel (Android update project -p .
en dan mierenpot
) en het importeren van uw POT bibliotheek in uw Android Studio-project met een eenvoudige compileer bestanden ('libs / volley.jar')
.
Onlangs echter heeft Google Volley bijgewerkt naar de buildstijl van Android Studio, waardoor het moeilijker is om een zelfstandige versie te maken POT. Je kunt het nog steeds doen, maar alleen met oudere versies van de bibliotheek. Ik ontmoedig je persoonlijk om deze optie te gebruiken, ook al lijkt dit het snelst.
Je moet Volley instellen klassieke manier, dat wil zeggen, door de bron te importeren als een module. Selecteer in Android Studio, met uw project geopend Bestand> Nieuwe module, en kies Bestaand project importeren. Selecteer de map waar u de broncode zojuist hebt gedownload en bevestig. Een map genaamd Volley verschijnt in uw projectstructuur. Android Studio werkt je updates automatisch bij settings.gradle bestand om de Volley-module op te nemen, zodat u alleen hoeft toe te voegen aan uw afhankelijkheden compileer project (': volley')
en je bent klaar.
Er is een derde weg. U kunt toevoegen aan het gebied afhankelijkheid van de build.gradle bestand deze lijn:
compile 'com.mcxiaoke.volley: library-aar: 1.0.15'
Het is een kopie van de officiële repository van Google, regelmatig gesynchroniseerd en bijgewerkt. Het is waarschijnlijk de eenvoudigste en snelste manier om te beginnen. Houd er echter rekening mee, het is een officieus Maven-repository, geen garanties en niet ondersteund door Google.
Naar mijn mening is het nog steeds beter om nog een paar minuten te investeren in het importeren van de officiële broncode. Op deze manier kunt u eenvoudig naar de oorspronkelijke definities en implementaties springen, zodat u in geval van twijfel altijd kunt vertrouwen op de officiële bron van de Volley-en deze zelfs kunt wijzigen als u.
Volley werkt meestal met slechts twee klassen, RequestQueue
en Verzoek
. Je maakt eerst een RequestQueue
, die worker-threads beheert en de geparseerde resultaten terugstuurt naar de hoofdthread. Je geeft het dan een of meer door Verzoek
voorwerpen.
De Verzoek
constructor neemt altijd als parameters het methode type (GET, POST, etc.), de URL van de resource en gebeurtenislisteners. Vervolgens kan het, afhankelijk van het type verzoek, om wat meer variabelen vragen.
In het volgende voorbeeld maak ik een RequestQueue
object door een beroep te doen op een van Volley's gemaksmethoden, Volley.newRequestQueue
. Hiermee stelt u een RequestQueue
object, met behulp van standaardwaarden die zijn gedefinieerd door Volley.
String-URL = "http://httpbin.org/html"; // Vraag een string-antwoord aan StringRequest stringRequest = new StringRequest (Request.Method.GET, url, nieuwe Response.Listener() @Override public void onResponse (String response) // Resultaatafhandeling System.out.println (response.substring (0,100)); , nieuwe Response.ErrorListener () @Override public void onErrorResponse (VolleyError error) // Error handling System.out.println ("Er is iets misgegaan!"); error.printStackTrace (); ); // Voeg de aanvraag toe aan de wachtrij Volley.newRequestQueue (this) .add (stringRequest);
Zoals je ziet, is het ongelooflijk eenvoudig. U maakt de aanvraag en voegt deze toe aan de wachtrij voor aanvragen. En je bent klaar.
Merk op dat de listenersyntaxis vergelijkbaar is AsyncTask.onPostExecute
, het wordt gewoon onResponse
. Dit is geen toeval. De ontwikkelaars die aan Volley hebben gewerkt, hebben met opzet de API van de bibliotheek zo vergelijkbaar gemaakt met de AsyncTask
methoden. Dit maakt de overgang van het gebruik AsyncTask
naar Volley, dat veel gemakkelijker.
Als u meerdere aanvragen in meerdere activiteiten moet indienen, moet u de bovenstaande aanpak vermijden, Volley.newRequestQueue.add
. Het is veelbeter om een gedeelde wachtrij voor een aanvraag in te stellen en deze in uw project te gebruiken:
. MySingletonClass.getInstance () getRequestQueue () toe te voegen (myRequest).;
We zullen specifiek zien om zoiets te ontwikkelen in de volgende tutorial van deze serie.
Volley is handig voor het implementeren van drie veelvoorkomende aanvraagtypen:
StringRequest
ImageRequest
JsonRequest
Elk van deze klassen breidt het Resultaat
klasse die we eerder hebben gebruikt. We hebben al gekeken naar de StringRequest
in het vorige voorbeeld. Laten we in plaats daarvan zien hoe a JsonRequest
werken.
String url = "http://httpbin.org/get?site=code&network=tutsplus"; JsonObjectRequest jsonRequest = new JsonObjectRequest (Request.Method.GET, url, null, new Response.Listener() @Override public void onResponse (JSONObject-respons) // het antwoord is al geconstrueerd als een JSONObject! probeer response = response.getJSONObject ("args"); String site = response.getString ("site"), network = response.getString ("netwerk"); System.out.println ("Site:" + site + "\ nNetwerk:" + netwerk); catch (JSONException e) e.printStackTrace (); , nieuwe Response.ErrorListener () @Override public void onErrorResponse (VolleyError error) error.printStackTrace (); ); Volley.newRequestQueue (de) .Voeg (jsonRequest);
Mooi. Is het niet? Zoals u kunt zien, is het type resultaat al ingesteld op JSONObject
. U kunt vragen om een JSONArray
ook als je wilt, met behulp van een JsonArrayRequest
inplaats van een JsonObjectRequest
.
Zoals eerder is de eerste parameter van de constructor de HTTP-methode die moet worden gebruikt. Vervolgens geeft u de URL op voor het ophalen van de JSON. De derde variabele in het bovenstaande voorbeeld is nul
. Dit is goed omdat het aangeeft dat er geen parameters worden gepost samen met het verzoek. Ten slotte heb je de luisteraar om het JSON-antwoord en een foutluisteraar te ontvangen. Je kunt binnenkomen nul
als je fouten wilt negeren.
Het ophalen van afbeeldingen vereist wat meer werk. Er zijn drie mogelijke methoden om een afbeelding aan te vragen. ImageRequest
is de standaard. Het geeft de foto weer die u hebt aangevraagd in een standaard Figuurweergave
, ophalen via een opgegeven URL. Alle bewerkingen voor het decoderen en wijzigen van de grootte die u mogelijk wilt dat Volley presteert, vinden plaats op een werkthread. De tweede optie is de ImageLoader
klasse, die je kunt bedenken als orkestrator van een groot aantal ImageRequests
, om bijvoorbeeld a te vullen Lijstweergave
met afbeeldingen. De derde optie is NetworkImageView
, wat een soort XML-substituut is voor de Figuurweergave
lay-outitem.
Laten we een voorbeeld bekijken.
String-URL = "http://i.imgur.com/Nwk25LA.jpg"; mImageView = (ImageView) findViewById (R.id.image); ImageRequest imgRequest = new ImageRequest (url, nieuwe Response.Listener() @Override public void onResponse (Bitmap response) mImageView.setImageBitmap (response); , 0, 0, ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener () @Override public void onErrorResponse (VolleyError error) mImageView.setBackgroundColor (Color.parseColor ("# ff0000")) ; error.printStackTrace (); ); Volley.newRequestQueue (de) .Voeg (imgRequest);
De eerste parameter is de URL van de afbeelding en de tweede is de luisteraar voor het resultaat. De derde en vierde parameters zijn gehele getallen, Maximale wijdte
en maximale hoogte
. U kunt ze instellen 0
om deze parameters te negeren. Daarna, ImageRequest
vraagt je om de ScaleType
gebruikt om de benodigde afbeeldingsgrootte te berekenen en voor de indeling om de bitmap naar te decoderen. Ik stel voor altijd te gebruiken Bitmap.Config.ARGB_8888
. Ten slotte geven we een fout luisteraar door.
Merk op dat Volley automatisch de prioriteit van deze aanvraag instelt LAAG
.
// Snippet uit ImageRequest.java, // in de broncode van Volley @Overdracht openbaar Priority getPriority () return Priority.LOW;
Het omschakelen van een GET-verzoek naar een POST-aanvraag is eenvoudig. U moet de request.method
in de constructor van het verzoek en overschrijven de getParams
methode, een goede retourneren Kaart
met de parameters van het verzoek.
String-URL = "http://httpbin.org/post"; StringRequest postRequest = new StringRequest (Request.Method.POST, url, nieuwe Response.Listener() @Override public void onResponse (String response) try JSONObject jsonResponse = new JSONObject (response) .getJSONObject ("form"); String-site = jsonResponse.getString ("site"), network = jsonResponse.getString ("netwerk"); System.out.println ("Site:" + site + "\ nNetwerk:" + netwerk); catch (JSONException e) e.printStackTrace (); , nieuwe Response.ErrorListener () @Override public void onErrorResponse (VolleyError error) error.printStackTrace (); ) @Override beschermde kaart getParams () Map params = nieuwe HashMap <> (); // de POST-parameters: params.put ("site", "code"); params.put ("netwerk", "tutsplus"); terugkeer params; ; Volley.newRequestQueue (de) .Voeg (postRequest);
Als u al uw verzoeken wilt annuleren, voegt u het volgende codefragment toe aan de onStop
methode:
@Override beschermde leegte onStop () super.onStop (); mRequestQueue.cancelAll (nieuw RequestQueue.RequestFilter () @Override public boolean apply (Request> verzoek) // moet ik dit annuleren? geef waar terug; // -> altijd ja);
Op deze manier hoeft u zich geen zorgen te maken over de mogelijkheid dat de gebruiker de activiteit al heeft vernietigd wanneer onResponse
wordt genoemd. EEN NullPointerException
zou in zo'n geval worden gegooid.
POST- en PUT-verzoeken moeten echter worden voortgezet, zelfs nadat de gebruiker de activiteiten heeft gewijzigd. We kunnen dit bereiken door te gebruiken labels. Wanneer u een GET-aanvraag samenstelt, voegt u er een tag aan toe.
// na het declareren van uw verzoek request.setTag ("GET"); mRequestQueue.add (verzoek);
Om elke openstaande GET-aanvraag te annuleren, voegen we eenvoudig de volgende regel code toe:
mRequestQueue.cancelAll ( "GET");
Op deze manier annuleert u alleen de GET-verzoeken, waardoor andere verzoeken onaangeroerd blijven. Merk op dat u nu handmatig de zaak moet behandelen waarin de activiteit voortijdig wordt vernietigd.
Volley biedt geen methode voor het instellen van de cookies van een verzoek, noch de prioriteit ervan. Waarschijnlijk in de toekomst, omdat het een ernstige omissie is. Voorlopig moet je echter het Verzoek
klasse.
Voor het beheer van cookies kunt u met de headers van het verzoek spelen en de getHeaders
methode:
public class CustomRequest breidt JsonObjectRequest uit // Aangezien we een Request-klasse uitbreiden // gebruiken we alleen de constructor public CustomRequest (int-methode, String-URL, JSONObject jsonRequest, Response.Listenerlistener, Response.ErrorListener errorListener) super (methode, url, jsonRequest, listener, errorListener); privé-kaart headers = nieuwe HashMap <> (); / ** * Aangepaste klasse! * / public void setCookies (lijst cookies) StringBuilder sb = nieuwe StringBuilder (); for (String cookie: cookies) sb.append (cookie) .append (";"); headers.put ("Cookie", sb.toString ()); @Overige openbare kaart getHeaders () gooit AuthFailureError return headers;
Met deze implementatie kunt u direct de lijst met cookies voor het verzoek opgeven via setCookies
.
// Allereerst maakt u de lijst met cookies, // conform de HTTP-conventies // d.w.z. sleutel = waarde Lijstcookies = nieuwe ArrayList <> (); cookies.add ( "site = code"); cookies.add ( "network = tutsplus"); // dan roep je je aangepaste methode customRequest.setCookies (cookies) aan; // en voeg tenslotte het verzoek toe aan de wachtrij Volley.newRequestQueue (this) .add (customRequest);
Voor de prioriteit moet u ook het Verzoek
klasse, overschrijft de getPriority
methode. Dit is hoe de implementatie eruit zou kunnen zien:
Prioriteit mPriority; public void setPriority (Priority priority) mPriority = priority; @Override public Priority getPriority () // Als u de methode setPriority niet heeft gebruikt // wordt de prioriteit automatisch ingesteld op NORMAL return mPriority! = Null? mPriority: Priority.NORMAL;
Voer vervolgens op de hoofdthread deze regel code in om de prioriteit van de aanvraag in te stellen:
customRequest.setPriority (Priority.HIGH);
U kunt kiezen uit een van de vier mogelijke prioriteitstoestanden, zoals hieronder getoond:
Priority.LOW // afbeeldingen, miniaturen, ... Priority.NORMAL // rest Priority.HIGH // beschrijvingen, lijsten, ... Priority.IMMEDIATE // login, logout, ...
In dit artikel hebben we gekeken naar hoe de netwerkbibliotheek van Volley werkt. We hebben eerst gezien waarom en wanneer het beter is om Volley te gebruiken in plaats van een andere oplossing die al is opgenomen in de Android SDK. Vervolgens hebben we diep in de details van de bibliotheek gedoken, gekeken naar de workflow en de ondersteunde aanvraagtypen. Ten slotte hebben we onze handen vervuild door het maken van eenvoudige verzoeken en het implementeren van aangepaste aanvragen voor het afhandelen van cookies en het stellen van prioriteiten.
In het volgende deel van deze serie over Volley maken we een eenvoudige applicatie die gebruik maakt van Volley. Ik zal je laten zien hoe je een weerapplicatie voor Mars kunt maken, met behulp van weergegevens die op Mars zijn verzameld door de Curiosity rover.
Als u veel Android-ontwikkeling uitvoert, kunt u uw workflow versnellen door een van de duizenden handige Android-app-sjablonen te gebruiken die beschikbaar zijn op Envato Market? Of neem contact op met een van de Android-ontwikkelaars op Envato Studio om u te helpen met uw project - ze kunnen zelfs uw app vanaf de grond af ontwerpen!