Creating et Været Søknad om Mars Bruke Volley
23
Del
3
Del
Dette Cyber Monday Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.
Dette innlegget er en del av en serie som heter An Introduction to Volley.An Introduksjon til VolleyWhat du skal lage
Innledning
I denne opplæringen, vil jeg vise deg en mulig bruk tilfelle av det vi lærte i forrige artikkel om Volley. Vi willcreate en vær søknad om Mars, ved hjelp av informasjonen som samles inn av Curiosity rover, som er gjort tilgjengelig for alle ved NASA gjennom {MAAS} API.
Først vil vi sette opp prosjektet i Android Studio og designe bruker interface.We vil da strukturere kjernen av programmet som bruker Volley. Siden hver vakker Søknaden har noen bilder, vil jeg vise youhow å hente en tilfeldig en bruker Flickr API. Vi vil laste ned bildet med Volley, hovedsakelig på grunn av sin store caching system.Finally, vil vi legge til noen fancy detaljer for å gi programmet en gorgeouslook og føler.
1. Prosjektet Setup
Først oppretter et nytt prosjekt i Android Studio. Siden Volley er bakoverkompatibel, kan du choosewhatever API nivå du foretrekker. Jeg har valgt API 21, men du bør være greit så lenge API nivå er 8 (Froyo) eller høyere
Trinn 1:. User Interface
Vår søknad har et enkelt, enkel aktivitet . Du kan kalle det MainActivity.java
, som foreslått av Android Studio. Åpne layouteditor og dobbeltklikk activity_main.xml
.
Siden vi ønsker å ha ca 70% av skjermen dedikert til bildet andthe resten til værinformasjon, må vi bruke XML-attributtet layout_weight. Selvfølgelig, kan vi bruke absolutevalues også, men det ville ikke være den samme. Dessverre, Android verden har skjermer som er alt annet enn homogent, andspecifying en absolutt verdi for høyden på bildet kan resultere i en 90-10 ratio på svært smalldevices og en 70-30, eller enda en 60-40 forhold, på større enheter. Den layout_weight
attributt er hva du trenger for å løse dette problemet
< LinearLayout xmlns:. Android = "http://schemas.android.com/apk/res/android" android: layout_width = " match_parent "android: layout_height =" match_parent "android: orientering =" vertikal "> < RelativeLayout android: layout_width = "match_parent" android: layout_height = "0DP" android: layout_weight = "0,68" android: bakgrunn = "# FF5722" > <! - image - > < /RelativeLayout > < RelativeLayout android: layout_weight = "0,33" android: layout_height = "0DP" android: layout_width = "match_parent" android: paddingTop = "@ dimen /activity_horizontal_margin" android: bakgrunn = "# 212121" > <! - TextViews - > < /RelativeLayout > < /LinearLayout >
Inside thefirst barnet, legger Imageview:
< Imageview android: id = "+ id /main_bg" android: layout_width = "match_parent" android: layout_height = " match_parent "android: scaleType =" centerCrop "/>
I thesecond RelativeLayout, legger vi en liste over TextView elementer. To av dem er utsikt i hvilken den gjennomsnittlige temperaturen og stemningen opacity vises. Den tredje er en feil etikett
< TextView android. Id = "+ id /error" android: layout_centerInParent = "true" android: synlighet = "borte" android: layout_height = "wrap_content" android: layout_width = " match_parent "android: Tekststørrelse =" 20sp "android: textcolor =" # FF5722 "android: layout_margin =" @ dimen /activity_horizontal_margin "android: vekt =" center "android: text =" Jeg beklager \\ nI var ikke i stand til. å hente sanntidsdata. "/> < TextView android: id =" + id /grader "android: layout_height =" wrap_content "android: layout_width =" wrap_content "android: layout_centerHorizontal =" true "android: Tekststørrelse =" 90sp "android: textcolor =" # FF5722 "android: text =" - 36 ° "/> < TextView android: id =" + id /vær "android: layout_width =" wrap_content "android: layout_height =" wrap_content " android: layout_centerHorizontal = "true" android: layout_below = "@ id /grader" android: Tekststørrelse = "30sp" android: vekt = "center" android: textcolor = "# FF5722" android: text = "Sunny" /> < p> Oppsettet skal nå være komplett. Du kan legge til flere detaljer om du vil, men en kompleks og detaljert brukergrensesnittet er ikke innenfor rammen av denne opplæringen
Trinn 2:. Tema og Tillatelser
Det er to mer ting vi må ta vare på før du begynner å grave i kjernen av søknaden. Endre arvet tema av søknaden til android: Theme.Material.Light.NoActionBar. Dette betyr at vi ikke trenger å skjule handlingsfeltet under kjøring
< style name = "AppTheme" foreldre =. "Android: Theme.Material.Light.NoActionBar" />
Til slutt legger Internett tillatelse til prosjektets manifest
< bruker-tillatelse android. name = "android.permission.INTERNET" />
2. Søknad Kjerne
Trinn 1: Import Volley
aswe diskutert i den forrige artikkelen, den enkleste og mostreliable måte å bruke Volley er ved å importere biblioteket som en ny module.Download kildekoden til bibliotek, importere den via Fil > New > Modul, og fortelle kompilatoren i prosjektets build.gradle fil for å ta det med i prosjektet
kompilere prosjektet (": volley").
Trinn 2: Implementere Helper Class
Som Ialready påpekt i forrige artikkel, hvis du trenger å fyre flere forespørsler, er det bedre å bruke en felles anmodning køen. Du bør unngå å skape en forespørsel kø hver gang du planlegger en forespørsel ved å påberope Volley.newRequestQueue, fordi du ikke ønsker å ende opp med minnelekkasjer og andre uønskede problemer.
For å gjøre det, må du først lage en klasse ved hjelp av Singleton mønster. Klassen er referert med en statisk, globalt synlig variabel, som deretter håndterer objektet RequestQueue. På denne måten vil du ende opp med et enkelt RequestQueue for søknaden. Deretter utvide Application klasse, må du fortelle til operativsystemet for å generere dette objektet når programmet startes, selv før den første aktiviteten er opprettet.
Siden vi er i Android miljø, vi litt modifisere felles singleton struktur. Klassen trenger for å lage en ny forekomst av seg selv i Application.onCreate metode-ikke i en generisk getInstance metoden når det er null.
For å achievethis, opprette en ny klasse og gi den navnet MarsWeather.java
. Deretter forlenge Android Application klasse, overstyre theonCreate metode, og initialisere RequestQueue gjenstand for thestatic eksempel.
I singleton klasse, vi konstruere objekt av klassen ved hjelp av en offentlig og synkronisert funksjon getInstance. Inne i denne metoden, returnerer vi mInstance variabel. Den onCreate metoden startes når programmet startes så mInstance variable vil allerede være satt første gang getInstance metode kalles
public class MarsWeather strekker Application {private RequestQueue mRequestQueue.; private static MarsWeather mInstance; Override Public void onCreate () {super.onCreate (); mInstance = dette; mRequestQueue = Volley.newRequestQueue (getApplicationContext ()); } Public static synkronisert MarsWeather getInstance () {return mInstance; }}
Deretter fortelle i AndroidManifest.xml filen du vil MarsWeather å bli lastet når programmet startes. I < søknaden > tag, legge til attributtet navn som følger:
android: name = ". MarsWeather"
Det var det. En forekomst av Applikasjonen klassen er opprettet, selv før MainActivity er opprettet. Sammen med alle de andre standardoperasjoner, genererer onCreate en forekomst av RequestQueue.
Vi må gjennomføre tre andre metoder for å gjøre ferdig hjelperen klassen. Den første metoden erstatter Volley.newRequestQueue, som jeg vil nevne getRequestQueue. Vi trenger også en metode for å legge en forespørsel til køen, legge til, og en metode som er responsiblefor avlyser forespørsler, avbryte. . Den følgende kode blokken viser hva gjennomføringen ser ut
offentlig RequestQueue getRequestQueue () {return mRequestQueue;} public < T > void add (Request < T > req) {req.setTag (TAG); getRequestQueue () legge til (req);.} public void avbryt () {mRequestQueue.cancelAll (TAG);}
TAG er en generisk token du bruker til å identifisere forespørsel. I dette konkrete tilfellet, kan det bli hva du vil:
public static endelige String TAG = MarsWeather.class.getName ();
Trinn 3: Gjennomføre Custom Request
Som youalready vet, Volley gir tre standard forespørsel typer: StringRequest, ImageRequest, og JsonRequest. Vår søknad kommer til å bruke sistnevnte for å hente værdata og hente en liste av tilfeldige bilder.
Som standard Volley setsthe prioritering av forespørselen til NORMAL. Vanligvis som ville befine, men i vår søknad har vi to forespørsler som er ganske annerledes, og vi trenger derfor å ha en annen prioritet i thequeue. Henter været data må ha en høyere prioritet enn å hente inn nettadressen til tilfeldig bilde.
Derfor må vi tilpasse theJsonRequest klasse. Lag en newclass heter CustomJsonRequest.java, og sørg for at den strekker JsonObjectRequest. Deretter overstyre getPriority metoden som vist nedenfor
public class CustomJsonRequest strekker JsonObjectRequest {public CustomJsonRequest. (Int metode, String url, JSONObject jsonRequest, Response.Listener < JSONObject > lytteren, Response.ErrorListener errorListener) {super (metode, url , jsonRequest, lytter, errorListener); } Private Priority mPriority; public void setPriority (Priority prioritet) {mPriority = prioritet; }Override Offentlig Priority getPriority () {return mPriority == null? Priority.NORMAL: mPriority; }}
Trinn 4: Henter data
Vi finallyarrived til den mest interessante delen av denne opplæringen der skriver vi implementationto henter værdata. Endepunktet for anmodningen er:
http://marsweather.ingenology.com/v1/latest/
The APIer er søkbar så åpne lenken for å inspisere den resulterende JSON. JSON inneholder et enkelt objekt, resultat, som inkluderer en rekke strenger, alt fra temperaturer towind retning og solnedgang tid
Start med å erklære følgende variabler i MainActivity klassen.
TextView mTxtDegrees, mTxtWeather, mTxtError; MarsWeather helper = MarsWeather.getInstance (); endelig statisk string RECENT_API_ENDPOINT = "http://marsweather.ingenology.com/v1/latest/";
You kan kalle MarsWeather.getInstance utenfor onCreate. Siden klassen vil allerede være initialisert, trenger du ikke å vente på onStart metode for å kalle det. Selvfølgelig, må du sette referansene av visningene brukergrensesnittet i
onCreate metoden
mTxtDegrees = (TextView) findViewById (R.id.degrees);. MTxtWeather = (TextView) findViewById (R .id.weather); mTxtError = (TextView) findViewById (R.id.error);
Afterdoing det, er det på tide å gjennomføre loadWeatherData metoden. Vi skaper en tilpasset Volley forespørsel og angi prioritet til HIGH. Vi deretter påberope hjelperen add metode for å legge den til forespørselen køen. Det som er viktig å merke seg er resultatet lytteren, siden det kommer til å påvirke brukergrensesnittet
private void loadWeatherData () {CustomJsonRequest forespørsel = new CustomJsonRequest (Request.Method.GET, RECENT_API_ENDPOINT, null, ny Response.Listener. ≪ JSONObject > () {Override public void onResponse (JSONObject respons) {try {String minTemp, maxTemp, atmo; int avgTemp; respons = response.getJSONObject ("rapporten"); minTemp = response.getString ("min_temp"); minTemp = minTemp.substring (0, minTemp.indexOf () "."); maxTemp = response.getString ("max_temp"); maxTemp = maxTemp.substring ("." 0, maxTemp.indexOf ()); avgTemp = (Integer. parseInt (minTemp) + Integer.parseInt (maxTemp)) /2; atmo = response.getString ("atmo_opacity"); mTxtDegrees.setText (avgTemp + "°"); mTxtWeather.setText (atmo); } Catch (Exception e) {txtError (e); }}}, Ny Response.ErrorListener () {Override public void onErrorResponse (VolleyError feil) {txtError (feil); }}); request.setPriority (Request.Priority.HIGH); helper.add (forespørsel);}
Asyou kan se, den metoden tar minimum og maksimum temperaturene, beregner gjennomsnittstemperaturen, og oppdaterer brukergrensesnittet. Ialso implementert en enkel metode for å håndterer feil
private void txtError (Exception e) {mTxtError.setVisibility (View.VISIBLE.); e.printStackTrace ();}
Vi har nå bare trenger å callloadWeatherData i onCreate og du er ferdig. Appen er nowready å vise været på Mars.
3. Henter Image Data
Nå thatyou har kjernen av programmet klar og fungerer, kan vi fokusere på å gjøre programmet visuelt mer tiltalende. Vi kommer til å gjøre dette ved å hente en tilfeldig Mars image og vise den til brukeren
Trinn 1:. Fetch et tilfeldig bilde
Du trenger en Flickr API-nøkkel for å hente en tilfeldig listof contextualized bilder. Bildet punktet er following:
https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&sort=random&method=flickr.photos.search&tags=mars,planet,rover&tag_mode=all&api_key=[YOUR_KEY]
As du cansee, forespørselen er ganske enkel. Du forteller Flickr for å gi youresults formatert som JSON (format = JSON), men vi vet ikke spesifiserer en JSON tilbakeringing (nojsoncallback = 1). Du søker et bilde (method = flickr.photos.search) og kodene du er interessert i er relatert til Mars (tags = mars, planet, rover). Ta en titt på dokumentasjonen for mer informasjon om formatet på forespørsel URL
Start med å erklære følgende variabler:.
Endelige statisk String FLICKR_API_KEY = "[SETT INN HER DIN API KEY]" , IMAGES_API_ENDPOINT = "https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&sort=random&method=flickr.photos.search&" + "Tags = mars, planet, rover & tag_mode = all & api_key =";
Deretter implementere searchRandomImage metode:
private void searchRandomImage () kaster Exception {if (FLICKR_API_KEY.equals ("")) throw new Exception ("Du har ikke en arbeider Flickr API!"); CustomJsonRequest forespørsel = new CustomJsonRequest (Request.Method.GET, IMAGES_API_ENDPOINT + FLICKR_API_KEY, null, ny Response.Listener < JSONObject > () {Override public void onResponse (JSONObject respons) {try {JSONArray bilder = response.getJSONObject ("bilder") .getJSONArray ("bilder"); int index = new Random () nextInt (images.length ()); JSONObject imageItem = images.getJSONObject (indeks); String Bildeadresse =. "http: //farm" + imageItem.getString ( "Gården") + ".static.flickr.com /" + imageItem.getString ("server") + "/" + imageItem.getString ("id") + "_" + imageItem.getString ("hemmelig") + "_" + "c.jpg"; //TODO: gjøre noe med * Bildeadresse *} catch (Exception e) {imageError (e);}}}, ny Response.ErrorListener () {Override public void onErrorResponse (VolleyError error) {imageError (feil); }}); request.setPriority (Request.Priority.LOW); helper.add (forespørsel);}
Som du kan se, sender Flickr tilbake en JSONArray inneholder bildene. Metoden skrev for å hente en tilfeldig bilde genererer et tilfeldig tall mellom null og til størrelsen av rekken. Det tar elementet tilsvarer at indeksen fra rekken av resultater og konstruerer URL for bildet følge disse retningslinjene
Som før, trenger vi en metode for feilbehandling.
Int mainColor = Color.parseColor ("# FF5722"); private void imageError (Exception e) {mImageView.setBackgroundColor (mainColor); e.printStackTrace ();}
Til slutt ringe searchRandomImage i onCreate metoden og ikke glem å fange eventuelle unntak
Trinn 2:. Sjekk Picture
Nå som Vihar en URL å laste, kan vi vise bildet. Du har allerede lært hvordan du gjør dette i den forrige artikkelen.
Private void loadImg (String Bildeadresse) {//Henter et bilde angitt av URL, og viser det i UI ImageRequest forespørsel = new ImageRequest (Bildeadresse, ny Response.Listener < Bitmap > () {Override public void onResponse (Bitmap bitmap) {mImageView.setImageBitmap (bitmap);}}, 0, 0, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, ny Response.ErrorListener () {public void onErrorResponse (VolleyError feil) {imageError (feil);}}); //Vi ikke trenger å angi prioritet her; //ImageRequest kommer allerede på med //prioritet satt til LAV, det er akkurat det vi trenger. helper.add (forespørsel);}
I onResponse metoden vi skrev i forrige trinn, er vi endelig i stand til å håndtere resultatet
loadImg (Bildeadresse);
Trinn 3:. Viser et nytt bilde hver Dag
Kanskje youalready lagt merke til at vi er omgåelsen Volley er caching system ved å hente et tilfeldig bilde hver gang programmet startes. Vi må finne en wayto vise det samme bildet på en bestemt dag.
Den enkleste måten å oppnå dette på er ved hjelp Android'sSharedPreferences. Start med å erklære de variablene vi trenger for denne
SharedPreferences mSharedPref.; int dag = Calendar.getInstance () får (Calendar.DAY_OF_MONTH);. endelige statiske String SHARED_PREFS_IMG_KEY = "img", SHARED_PREFS_DAY_KEY = "dag";
Neste, i onCreate metoden, før samtalen til searchRandomImage, initial mSharedPref.
mSharedPref = getPreferences (Context.MODE_PRIVATE);
Ideen er å storethe gjeldende dag hver gang vi hente en ny tilfeldig bilde. Selvfølgelig, vi lagrer nettadressen til bildet ved siden av dagen. Når programmet starter, sjekker vi om vi allerede har en oppføring i SharedPreferences for den aktuelle dagen. Hvis vi har en kamp, vi bruker den lagrede URL. Ellers vi hente en tilfeldig bilde og lagre nettadressen i SharedPreferences
I searchRandomImage etter thedefinition av ImageURL, legge til følgende linjer med kode.
//Rett etter * String Bildeadresse =. ... * //lagre pict av daySharedPreferences.Editor redaktør = mSharedPref.edit (); editor.putInt (SHARED_PREFS_DAY_KEY, i dag), editor.putString (SHARED_PREFS_IMG_KEY, Bildeadresse); editor.commit (); //Og så er det * loadImage (Bildeadresse); *
TheonCreate metoden, etter definisjonen på mSharedPref, blir nå:
if (mSharedPref.getInt (SHARED_PREFS_DAY_KEY, 0) = i dag!) {//Søk og last en tilfeldig mars Pict try {searchRandomImage (); } Catch (Exception e) {//husk å sette din egen Flickr API! //Ellers vil jeg ikke være i stand til å vise //en tilfeldig Mars bilde imageError (e); }} Else {//vi allerede har en pict av dagen: la oss legge det loadImg (mSharedPref.getString (SHARED_PREFS_IMG_KEY, ""));} loadWeatherData ();
Det var det. Søknaden din er klar. Føl deg fri til å laste ned kildefilene for denne opplæringen på GitHub å se det ferdige prosjektet. Ta en titt på prosjektet det hvis du kjører inn i problemstillinger
Bonus. Tips: Bedre brukergrensesnitt
Trinn 1: Font
font som brukes i et brukergrensesnitt avgjør ofte utseendet og følelsen av et program. La oss begynne med å endre standard Robotofont med en mer tiltalende font, for eksempel Lato lys.
Opprett ny mappe som heter skrifter i mappe eiendeler
. Hvis du ikke finner den mappe eiendeler
, må du opprette itat samme nivå som java
mappe. Mappestrukturen skal se omtrent slik ut app \\ src \\ hoved \\ eiendeler \\ fonter
.
Kopier filen Lato-light.ttf
i fonter
mappe. I onCreate metoden, må du overstyre standardskrifttype av visningene der du ønsker å bruke den nye skrifttypen.
MTxtDegrees.setTypeface (Typeface.createFromAsset (getAssets (), "fonter /Lato- light.ttf ")); mTxtWeather.setTypeface (Typeface.createFromAsset (getAssets ()," fonter /Lato-light.ttf "));
Trinn 2: Transparent Status Bar
Etter retningslinjene for Android Material Design, kan vi få status bartransparent. På denne måten vil bakgrunnen være delvis synlig gjennom statuslinjen.
Du canachieve dette ved å gjøre en liten endring i programmets tema. Redigere prosjektets V21 \\ style.xml fil som dette:
< resources > < style name = "AppTheme" forelder = "android: Theme.Material.Light.NoActionBar" > < element name = "android: windowTranslucentStatus" > ekte < /element > < /style > < /ressurser >
Gjør surethat AndroidManifest.xml
er alreadyset å bruke temaet:
< søknad android: ". MarsWeather" name = android: allowBackup = "true" android: icon = "@ Mipmap /ic_launcher" android: label = "@ streng /APP_NAME" android: tema = "@ stil /AppTheme" >
Konklusjon
Wemade en lang reise. I den første artikkelen, begynte vi å snakke om Volley og dets applikasjoner. I denne opplæringen, så vi på en praktisk måte å gjennomføre theconcepts vi lært ved å bygge et vær program for Mars. Du skal nå ha en god forståelse av Volley biblioteket, hvordan det fungerer, og hva du kan bruke den til.