I denne opplæringen vil jeg vise deg en mulig brukstilstand av det vi lærte i forrige artikkel om Volley. Vi vil lage et værmeldingsprogram for Mars, ved hjelp av informasjonen som er innsamlet av nysgjerrighetsroveren, som gjøres tilgjengelig for alle av NASA gjennom MAAS API.
Først vil vi sette opp prosjektet i Android Studio og designe brukergrensesnittet. Vi vil da strukturere kjernen i søknaden ved hjelp av Volley. Siden hvert vakkert program inneholder noen bilder, vil jeg vise deg hvordan du henter en tilfeldig en ved hjelp av Flickrs API. Vi vil laste ned bildet med Volley, for det meste på grunn av det flotte caching-systemet. Til slutt vil vi legge til noen fancy detaljer for å gi applikasjonen et nydelig utseende.
Først opprett et nytt prosjekt i Android Studio. Siden Volley er bakoverkompatibel, kan du velge hvilket API-nivå du foretrekker. Jeg har valgt API 21, men du bør ha det bra så lenge API-nivået er 8 (Froyo) eller høyere.
Vår søknad har en enkel, enkel aktivitet. Du kan ringe det MainActivity.java, som foreslått av Android Studio. Åpne layoutredigeringsprogrammet og dobbeltklikk activity_main.xml.
Siden vi ønsker å ha ca 70% av skjermen dedikert til bildet og resten til værinformasjonen, må vi bruke XML-attributtet layout_weight
. Selvfølgelig kan vi også bruke absolutte verdier, men det ville ikke være det samme. Dessverre viser Android-verdensfunksjonene som er alt annet enn homogene, og å spesifisere en absolutt verdi for bildetes høyde kan resultere i et 90-10 forhold på svært små enheter og en 70-30 eller til og med en 60-40-forhold, på større enheter. De layout_weight
Attributt er det du trenger for å løse dette problemet.
Inne i det første barnet, legg til Imageview
:
I den andre RelativeLayout
, vi legger til en liste over TextView
elementer. To av dem er synspunkter der gjennomsnittstemperaturen og atmosfærens ustabilitet er vist. Den tredje er en feil etikett.
Oppsettet skal nå være komplett. Du kan legge til flere detaljer hvis du vil, men et komplekst og detaljert brukergrensesnitt er ikke innenfor rammen av denne opplæringen.
Det er to ting vi må ta vare på før du begynner å grave inn i kjernen i applikasjonen. Endre det arvede temaet til søknaden til android: Theme.Material.Light.NoActionBar
. Dette betyr at vi ikke trenger å skjule handlingslinjen ved kjøretid.
Til slutt legger du til internett-tillatelsen til prosjektets manifest.
Som vi diskuterte i forrige artikkel, er den enkleste og mest pålitelige måten å bruke Volley på, ved å importere biblioteket som en ny modul. Last ned kildekoden til biblioteket, importer den via Fil > Ny > modul, og fortell kompilatoren i prosjektets build.gradle fil for å inkludere den i prosjektet.
kompilere prosjekt (": volley")
Som jeg allerede påpekte i forrige artikkel, er det bedre å bruke en delt forespørselskø for å brenne flere forespørsler. Du bør unngå å opprette en forespørselskø hver gang du planlegger en forespørsel ved å påkalle Volley.newRequestQueue
, fordi du ikke vil 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ønsteret. Klassen refereres ved hjelp av en statisk, globalt synlig variabel, som deretter håndterer objektet RequestQueue
. På denne måten slutter du med en enkelt RequestQueue
for søknaden. Deretter utvider du applikasjon
klasse, må du fortelle til operativsystemet å generere dette objektet ved oppstart av programmet, selv før den første aktiviteten er opprettet.
Siden vi er i Android-miljøet, endrer vi litt av den enkle singleton strukturen. Klassen må skape en ny forekomst av seg selv i Application.onCreate
metode-ikke i en generisk getInstance
metode når det er null
.
For å oppnå dette, opprett en ny klasse og gi den navnet MarsWeather.java. Deretter skal du utvide Android applikasjon
klasse, tilsidesatte onCreate
metode, og initialiser RequestQueue
gjenstand for den statiske forekomsten.
I singleton-klassen konstruerer vi objektets klasse ved å bruke en offentlig
og synkronisert
funksjon getInstance
. Innenfor denne metoden returnerer vi mInstance
variabel. De onCreate
Metoden er påkalt når programmet startes, slik at mInstance
variabel vil allerede bli satt første gangen getInstance
Metoden er påkalt.
offentlig klasse MarsWeather strekker Applikasjon privat RequestQueue mRequestQueue; privat statisk MarsWeather mInstance; @Override public void onCreate () super.onCreate (); mInstance = dette; mRequestQueue = Volley.newRequestQueue (getApplicationContext ()); offentlig statisk synkronisert MarsWeather getInstance () return mInstance;
Neste, fortell i AndroidManifest.xml fil som du vil ha MarsWeather
å bli lastet ved oppstart av programmet. I
tag, legg til attributtet Navn
som følger:
android: name = "MarsWeather"
Det er det. En forekomst av applikasjon
klassen er opprettet, selv før Hoved aktivitet
er skapt. Sammen med alle de andre standardoperasjonene, onCreate
genererer en forekomst av RequestQueue
.
Vi må implementere tre andre metoder for å fullføre hjelpeklassen. Den første metoden erstatter Volley.newRequestQueue
, som jeg skal nevne getRequestQueue
. Vi trenger også en metode for å legge til en forespørsel i køen, Legg til
, og en metode som er ansvarlig for å kansellere forespørsler, Avbryt
. Følgende kodeblokk viser hvordan implementeringen ser ut.
offentlig RequestQueue getRequestQueue () return mRequestQueue; offentligvoid add (Request req) req.setTag (TAG); . GetRequestQueue () tilsett (req); offentlig ugyldig avbrytelse () mRequestQueue.cancelAll (TAG);
STIKKORD
er et generisk token du bruker til å identifisere forespørselen. I dette spesielle tilfellet kan det være hva du vil:
offentlig statisk endelig streng TAG = MarsWeather.class.getName ();
Som du allerede vet, tilbyr Volley tre standard forespørselstyper: StringRequest
, ImageRequest
, og JsonRequest
. Vår søknad skal bruke sistnevnte til å hente værdata og hente listen over tilfeldige bilder.
Som standard angir Volley prioriteten til forespørselen til NORMAL
. Vanligvis ville det være bra, men i vår søknad har vi to forespørsler som er ganske forskjellige, og vi må derfor ha en annen prioritet i køen. Å hente værdata må ha høyere prioritet enn å hente nettadressen til det tilfeldige bildet.
Derfor må vi tilpasse JsonRequest
klasse. Opprett en ny klasse som heter CustomJsonRequest.java, og sørg for at den strekker seg JsonObjectRequest
. Deretter overstyre getPriority
metode som vist nedenfor.
offentlig klasse CustomJsonRequest utvider JsonObjectRequest public CustomJsonRequest (int metode, String url, JSONObject jsonRequest, Response.Listenerlytter, Response.ErrorListener errorListener) super (metode, url, jsonRequest, lytter, errorListener); privat prioritet mPriority; Offentlig tomt settPrioritet (Prioritet prioritet) mPriority = Prioritet; @Override public Priority getPriority () return mPriority == null? Prioritet.NORMAL: mPrioritet;
Vi er endelig kommet til den mest interessante delen av denne opplæringen der vi skriver implementeringen for å hente værdataene. Endemålet for forespørselen er:
http://marsweather.ingenology.com/v1/latest/
APIene kan leses, så åpne lenken for å inspisere den resulterende JSON. JSON inneholder en enkel gjenstand, resultat
, som inkluderer en serie strenger, alt fra temperatur til vindretning og solnedgangstid.
Begynn med å deklarere følgende variabler i Hoved aktivitet
klasse:
TextView mTxtDegrees, mTxtWeather, mTxtError; MarsWeather Helper = MarsWeather.getInstance (); endelig statisk streng RECENT_API_ENDPOINT = "http://marsweather.ingenology.com/v1/latest/";
Du kan ringe MarsWeather.getInstance
utenfor onCreate
. Siden klassen allerede vil bli initialisert, trenger du ikke å vente på onStart
metode for å ringe det. Selvfølgelig må du sette referansene til brukergrensesnittet ide onCreate
metode.
mTxtDegrees = (TextView) findViewById (R.id.degrees); mTxtWeather = (TextView) findViewById (R.id.weather); mTxtError = (TextView) findViewById (R.id.error);
Etter å ha gjort det, er det på tide å implementere loadWeatherData
metode. Vi lager en tilpasset Volley-forespørsel og setter prioriteten til HØY
. Vi anvender deretter hjelperens Legg til
metode for å legge den til forespørselskøen. Det viktige å merke seg er resultatlytteren, siden det kommer til å påvirke brukergrensesnittet.
privat ugyldig belastningWeatherData () CustomJsonRequest request = ny CustomJsonRequest (Request.Method.GET, RECENT_API_ENDPOINT, null, ny Response.Listener() @Override public void onResponse (JSONObject respons) prøv String minTemp, maxTemp, atmo; int avgTemp; respons = response.getJSONObject ("report"); 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); fangst (Unntak e) txtError (e); , ny Response.ErrorListener () @Override public void onErrorResponse (VolleyError feil) txtError (error); ); request.setPriority (Request.Priority.HIGH); helper.add (forespørsel);
Som du kan se, tar metoden minimum og maksimum temperatur, beregner gjennomsnittstemperaturen og oppdaterer brukergrensesnittet. Jeg implementerte også en enkel metode for å håndtere feil.
privat ugyldig txtError (Unntak e) mTxtError.setVisibility (View.VISIBLE); e.printStackTrace ();
Vi trenger nå bare å ringe loadWeatherData
i onCreate
og du er ferdig. Appen er nå klar til å vise været fra Mars.
Nå som du har kjernen i appen klar og klar, kan vi fokusere på å gjøre appen visuelt mer tiltalende. Vi skal gjøre dette ved å hente et tilfeldig Mars-bilde og vise det til brukeren.
Du trenger en Flickr API-nøkkel for å hente en tilfeldig liste over kontekstualiserte bilder. Bildens sluttpunkt er følgende:
https://api.flickr.com/services/rest/?format=json&nojsoncallback=1& sort = random & method = flickr.photos.search & tags = mars, planet, rover & tag_mode = alle & api_key = [YOUR_KEY]
Som du kan se, er forespørselen ganske enkel. Du forteller Flickr å gi deg resultater formatert som JSON (format = json
), men vi angir ikke en JSON tilbakeringing (nojsoncallback = 1
). Du søker et bilde (Fremgangsmåten = 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ørselsadressen.
Begynn med å erklære følgende variabler:
siste statiske streng FLICKR_API_KEY = "[INSERT HER DIN API KEY]", IMAGES_API_ENDPOINT = "https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&sort=random&method=flickr.photos.search&" + "tagger = mars, planet, rover og tag_mode = all & api_key = ";
Deretter implementerer du searchRandomImage
metode:
Private void searchRandomImage () kaster Unntak hvis (FLICKR_API_KEY.equals ("")) kaster ny unntak ("Du har ikke gitt en fungerende Flickr API!"); CustomJsonRequest request = ny CustomJsonRequest (Request.Method.GET, IMAGES_API_ENDPOINT + FLICKR_API_KEY, null, ny Response.Listener() @Override public void onResponse (JSONObject respons) prøv JSONArray images = response.getJSONObject ("photos"). GetJSONArray ("bilde"); int index = ny tilfeldig (). nextInt (images.length ()); JSONObject imageItem = images.getJSONObject (indeks); String imageUrl = "http: // farm" + imageItem.getString ("farm") + ".static.flickr.com /" + imageItem.getString ("server") + "/" + imageItem.getString ) + "_" + imageItem.getString ("hemmelig") + "_" + "c.jpg"; // TODO: gjør noe med * imageUrl * catch (Unntak e) imageError (e); , ny Response.ErrorListener () @Override public void onErrorResponse (VolleyError feil) imageError (error); ); request.setPriority (Request.Priority.LOW); helper.add (forespørsel);
Som du kan se, sender Flickr tilbake a JSONArray
inneholder bildene. Metoden jeg skrev for å hente et tilfeldig bilde genererer et tilfeldig tall mellom null og størrelsen på arrayet. Det tar elementet som tilsvarer den indeksen fra rekkevidden av resultater og konstruerer nettadressen for bildet som følger disse retningslinjene.
Som før, trenger vi en metode for feilhåndtering:
int mainColor = Color.parseColor ("# FF5722"); Privat tom bildeError (Unntak e) mImageView.setBackgroundColor (mainColor); e.printStackTrace ();
Til slutt, ring searchRandomImage
i onCreate
metode og ikke glem å ta noen unntak.
Nå som vi har en nettadresse å laste, kan vi vise bildet. Du har allerede lært hvordan du gjør dette i forrige artikkel.
Private void loadImg (String imageUrl) // Henter et bilde angitt av nettadressen, og viser det i brukergrensesnittet ImageRequest request = new ImageRequest (imageUrl, new Response.Listener() @Override Offentlig tomt-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 (error); ); // Vi trenger ikke å prioritere her; // ImageRequest kommer allerede inn med // prioritet satt til LOW, det er akkurat det vi trenger. helper.add (forespørsel);
I onResponse
metode vi skrev i forrige trinn, er vi endelig i stand til å håndtere resultatet.
loadImg (Bildeadresse);
Kanskje du allerede har lagt merke til at vi omgår Volleys caching-system ved å hente et tilfeldig bilde hver gang applikasjonen startes. Vi må finne en måte å vise det samme bildet på en bestemt dag.
Den enkleste måten å oppnå dette på er å bruke Android SharedPreferences
. Begynn med å erklære variablene vi trenger for dette.
SharedPreferences mSharedPref; int idag = Calendar.getInstance (). get (Kalender.DAY_OF_MONTH); Endelig statisk streng SHARED_PREFS_IMG_KEY = "img", SHARED_PREFS_DAY_KEY = "dag";
Deretter i onCreate
metode, før anropet til searchRandomImage
, initial mSharedPref
.
mSharedPref = getPreferences (Context.MODE_PRIVATE);
Tanken er å lagre dagens dag hver gang vi henter et nytt tilfeldig bilde. Selvfølgelig lagrer vi URL-adressen til bildet ved siden av dagen. Når søknaden lanseres, kontrollerer vi om vi allerede har en oppføring i SharedPreferences
for dagens dag. Hvis vi har en kamp, bruker vi den lagrede nettadressen. Ellers henter vi et tilfeldig bilde og lagrer nettadressen i SharedPreferences
.
I searchRandomImage
, etter definisjonen av Bildeadresse
, legg til følgende kodelinjer:
// rett etter * String imageUrl = ... * // lagre bildet av dagen SharedPreferences.Editor editor = mSharedPref.edit (); editor.putInt (SHARED_PREFS_DAY_KEY, i dag); editor.putString (SHARED_PREFS_IMG_KEY, imageUrl); editor.commit (); // og så er det * loadImage (imageUrl); *
De onCreate
metode, etter definisjonen på mSharedPref
, blir nå:
hvis (mSharedPref.getInt (SHARED_PREFS_DAY_KEY, 0)! = i dag) // søk og legg inn en tilfeldig marspict try searchRandomImage (); fangst (Unntak e) // Husk å sette inn din egen Flickr API! // ellers vil jeg ikke kunne vise // et tilfeldig Mars bilde bildeError (e); ellers // vi har allerede et bilde av dagen: la oss laste den loadImg (mSharedPref.getString (SHARED_PREFS_IMG_KEY, "")); loadWeatherData ();
Det er det. Din søknad erklar. Ta gjerne ned kildefilene i denne opplæringen på GitHub for å se det gjennomførte prosjektet. Ta en titt på prosjektet hvis du kjører inn i problemer.
Skriften som brukes i et brukergrensesnitt, bestemmer ofte utseendet på et program. La oss begynne med å endre standard Roboto-skrift med en mer tiltalende skrift, for eksempel Lato-lys.
Opprett en ny mappe som heter fonter i eiendeler mappe. Hvis du ikke finner eiendeler mappe, må du opprette den på samme nivå som java mappe. Mappestrukturen skal se ut som om app \ src \ Main \ eiendeler \ fonts.
Kopier filen Lato-light.ttf i fonter mappe. I onCreate
metode, må du overstyre standard skrifttypen i visningene du vil bruke den nye skrifttypen til.
mTxtDegrees.setTypeface (Typeface.createFromAsset (getAssets (), "fonter / Lato-light.ttf")); mTxtWeather.setTypeface (Typeface.createFromAsset (getAssets (), "fonter / Lato-light.ttf"));
Etter retningslinjene for Android Material Design kan vi gjøre statuslinjen gjennomsiktig. På denne måten blir bakgrunnen delvis synlig gjennom statuslinjen.
Du kan oppnå dette ved å gjøre en liten endring i søknadens tema. Rediger prosjektets V21 \ style.xml filen som denne:
Pass på at AndroidManifest.xml er allerede satt til å bruke temaet:
Vi har gjort 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 å implementere begreper vi lærte ved å bygge et værprogram for Mars. Du bør nå ha en god forståelse av Volley-biblioteket, hvordan det fungerer, og hva du kan bruke det til.