În acest tutorial, vă voi arăta un posibil caz de utilizare a ceea ce am învățat în articolul precedent despre Volley. Vom crea o aplicație meteorologică pentru Marte, folosind informațiile colectate de roverul Curiozitate, care este pus la dispoziția tuturor de către NASA prin API-ul MAAS.
În primul rând, vom seta proiectul în Android Studio și vom proiecta interfața cu utilizatorul. Apoi vom structura nucleul aplicației utilizând Volley. Deoarece fiecare aplicație frumoasă include câteva imagini, vă voi arăta cum să preluați una aleatoră utilizând API-ul Flickr. Vom descărca imaginea cu Volei, în mare parte datorită sistemului său de cache mare. În cele din urmă, vom adăuga câteva detalii fanteziste pentru a oferi aplicației un aspect superb și simțire.
Mai întâi, creați un nou proiect în Android Studio. Din moment ce Volley este compatibil înapoi, puteți alege nivelul de API pe care îl preferați. Am optat pentru API 21, dar ar trebui să fii bine atâta timp cât nivelul API este de 8 (Froyo) sau mai mare.
Aplicația noastră are o singură activitate simplă. Puteți să-l sunați MainActivity.java, așa cum sugerează Android Studio. Deschideți editorul de aspect și faceți dublu clic activity_main.xml.
Deoarece am dori să avem aproximativ 70% din ecranul dedicat imaginii și restul informațiilor despre vreme, trebuie să folosim atributul XML layout_weight
. Desigur, putem folosi și valori absolute, dar nu ar fi la fel. Din nefericire, afisajele cu caracteristici mondiale Android care nu sunt omogene, și specificând o valoare absolută pentru înălțimea imaginii ar putea avea ca rezultat un raport 90-10 pe dispozitive foarte mici și o relație de 70-30 sau chiar 60-40, pe dispozitive mai mari. layout_weight
atributul este ceea ce aveți nevoie pentru a rezolva această problemă.
În interiorul primului copil, adăugați ImageView
:
In secunda RelativeLayout
, adaugam o lista cu TextView
articole. Două dintre acestea sunt vederi în care sunt afișate temperatura medie și opacitatea atmosferei. A treia este o etichetă de eroare.
Arhitectura ar trebui să fie acum completă. Puteți adăuga mai multe detalii dacă doriți, dar o interfață complexă și detaliată a utilizatorului nu se află în sfera acestui tutorial.
Există încă două lucruri de care trebuie să avem grijă înainte de a începe să sapăm în nucleul aplicației. Modificați tema moștenită a aplicației la Android: Theme.Material.Light.NoActionBar
. Aceasta înseamnă că nu trebuie să ascundem bara de acțiune la momentul executării.
În final, adăugați permisiunea de acces la manifestarea proiectului.
Așa cum am discutat în articolul precedent, cea mai simplă și cea mai fiabilă modalitate de a utiliza Volley este importarea bibliotecii ca un nou modul. Descărcați codul sursă al bibliotecii, importați-l prin Fişier > Nou > Modul, și spuneți compilatorului în proiect build.gradle fișier pentru ao include în proiect.
compilați proiectul (": volei")
După cum am subliniat deja în articolul precedent, dacă trebuie să trageți mai multe solicitări, este mai bine să utilizați o coadă de solicitare partajată. Ar trebui să evitați să creați o coadă de solicitare de fiecare dată când programați o solicitare invocând Volley.newRequestQueue
, pentru că nu doriți să ajungeți la scurgeri de memorie și alte probleme nedorite.
Pentru a face acest lucru, mai întâi trebuie să creați o clasă utilizând modelul singleton. Clasa este referită folosind o variabilă statică, vizibilă la nivel global, care apoi gestionează obiectul RequestQueue
. În acest fel, veți termina cu un singur RequestQueue
pentru aplicație. Apoi, extinderea cerere
, trebuie să spuneți sistemului de operare să genereze acest obiect la pornirea aplicației, chiar înainte de crearea primei activități.
Deoarece suntem în mediul Android, modificăm puțin structura comună singleton. Clasa trebuie să creeze o nouă instanță în sine Application.onCreate
metodă - nu într-o generică getInstance
atunci când este nul
.
Pentru a realiza acest lucru, creați o nouă clasă și denumiți-o MarsWeather.java. Apoi, extindeți Android cerere
clasa, suprascrie onCreate
metodă și inițializați RequestQueue
obiect al instanței statice.
În clasa singleton, construim obiectul clasei folosind a public
și sincronizate
funcţie getInstance
. În cadrul acestei metode, returnați mInstance
variabil. onCreate
metoda este invocată atunci când cererea este pornită, astfel încât mInstance
Variabila va fi deja setată pentru prima oară getInstance
metoda este invocată.
clasa publică MarsWeather extinde aplicația private RequestQueue mRequestQueue; privat static MarsWeather mInstance; @Override publice void onCreate () super.onCreate (); mInstance = aceasta; mRequestQueue = Volley.newRequestQueue (getApplicationContext ()); public static sincronizat MarsWeather getInstance () return mInstance;
Apoi, spuneți în AndroidManifest.xml fișierul pe care îl doriți MarsWeather
să fie încărcate la pornirea aplicației. În
tag, adăugați atributul Nume
după cum urmează:
Android: name = "MarsWeather"
Asta e. O instanță a cerere
clasa este creată, chiar înainte Activitate principala
este creat. Împreună cu toate celelalte operațiuni standard, onCreate
generează o instanță a RequestQueue
.
Trebuie să implementăm alte trei metode pentru a termina clasa de ajutor. Prima metodă înlocuiește Volley.newRequestQueue
, pe care o voi numi getRequestQueue
. De asemenea, avem nevoie de o metodă pentru a adăuga o cerere la coadă, adăuga
, și o metodă responsabilă de anularea cererilor, Anulare
. Următorul bloc de coduri arată cum arată implementarea.
public RequestQueue getRequestQueue () retur mRequestQueue; publicevoid add (Solicitare req) req.setTag (TAG); . GetRequestQueue () se adaugă (req); public void cancel () mRequestQueue.cancelAll (TAG);
ETICHETĂ
este un simbol generic pe care îl utilizați pentru a identifica solicitarea. În acest caz specific, poate fi orice vreți:
public static final String TAG = MarsWeather.class.getName ();
După cum știți deja, Volley oferă trei tipuri standard de solicitări: StringRequest
, ImageRequest
, și JsonRequest
. Aplicația noastră o va folosi pe aceasta din urmă pentru a prelua datele despre vreme și pentru a recupera lista de imagini aleatorii.
Implicit, Volley stabilește prioritatea solicitării la NORMAL
. De obicei ar fi bine, dar în aplicația noastră avem două cereri care sunt foarte diferite și, prin urmare, trebuie să avem o prioritate diferită în coada de așteptare. Preluarea datelor meteorologice trebuie să aibă o prioritate mai mare decât preluarea adresei URL a imaginii aleatorii.
Din acest motiv, trebuie să personalizăm JsonRequest
clasă. Creați o nouă clasă numită CustomJsonRequest.java, și asigurați-vă că se extinde JsonObjectRequest
. Apoi, ignorați getPriority
așa cum se arată mai jos.
clasa publică CustomJsonRequest extinde JsonObjectRequest public CustomJsonRequest (metoda int, URL-ul String, JSONObject jsonRequest, Response.Listenerascultător, eroare Response.ErrorListenerListener) super (metoda, url, jsonRequest, ascultător, errorListener); prioritate privată mPriority; set de priorități publice prioritare mPriority = priority; @Override public Priority getPriority () return mPriority == null? Prioritate.NORMAL: mPrioritate;
Am ajuns în cele din urmă la cea mai interesantă parte a acestui tutorial, în care scriem implementarea pentru a obține datele meteorologice. Punctul final al cererii este:
http://marsweather.ingenology.com/v1/latest/
API-urile sunt navigabile, astfel încât să deschideți linkul pentru a inspecta rezultatul JSON. JSON conține un obiect simplu, rezultat
, care include o serie de șiruri de caractere, variind de la temperaturi până la direcția vântului și de la apusul soarelui.
Începeți prin a declara următoarele variabile în Activitate principala
clasă:
TextView mTxtDegrees, mTxtWeather, mTxtError; MarsWeather helper = MarsWeather.getInstance (); ultimul șir static RECENT_API_ENDPOINT = "http://marsweather.ingenology.com/v1/latest/";
Poti suna MarsWeather.getInstance
in afara de onCreate
. Deoarece clasa va fi deja inițializată, nu trebuie să așteptați onStart
metoda de ao numi. Desigur, trebuie să setați referințele din vizualizările interfeței utilizator în onCreate
metodă.
mTxtDegrees = (TextView) findViewById (R.id.degrees); mTxtWeather = (TextView) findViewById (R.id.weather); mTxtError = (TextView) findViewById (R.id.error);
După ce faceți acest lucru, este timpul să implementați loadWeatherData
metodă. Creăm o cerere personalizată Volley și setăm prioritatea la ÎNALT
. Apoi invocăm ajutoarele adăuga
metodă de adăugare la coada de solicitare. Cel mai important lucru pe care trebuie să-l observați este rezultatul ascultătorului, deoarece va afecta interfața cu utilizatorul.
private void loadWeatherData () CustomJsonRequest request = nou CustomJsonRequest (Request.Method.GET, RECENT_API_ENDPOINT, null, new Response.Listener() @Override public void peResponse (răspunsul JSONObject) try String minTemp, maxTemp, atmo; int avgTemp; răspuns = răspuns.getJSONObject ("raport"); minTemp = răspuns.getString ("min_temp"); minTemp = minTemp.substring (0, minTemp.indexOf (".")); maxTemp = răspuns.getString ("max_temp"); maxTemp = maxTemp.substring (0, maxTemp.indexOf (".")); avgTemp = (Integer.parseInt (minTemp) + Integer.parseInt (maxTemp)) / 2; atmo = răspuns.getString ("atmo_opacitate"); mTxtDegrees.setText (avgTemp + "°"); mTxtWeather.setText (Atmo); captură (Excepție e) txtError (e); , noul Response.ErrorListener () @Override public void peErrorResponse (eroare eroare eroare) txtError (eroare); ); request.setPriority (Request.Priority.HIGH); helper.add (cerere);
După cum puteți vedea, metoda ia temperaturile minime și maxime, calculează temperatura medie și actualizează interfața cu utilizatorul. De asemenea, am implementat o metodă simplă de tratare a erorilor.
private void txtError (excepție e) mTxtError.setVisibility (View.VISIBLE); e.printStackTrace ();
Acum trebuie doar să sunăm loadWeatherData
în onCreate
și ați terminat. Aplicația este acum gata să afișeze vremea lui Marte.
Acum, când aveți nucleul aplicației gata și lucrat, ne putem concentra pe a face aplicația vizuală mai atrăgătoare. Vom face acest lucru prin preluarea unei imagini aleatorii de pe Marte și afișarea acesteia către utilizator.
Veți avea nevoie de o cheie API Flickr pentru a prelua o listă aleatoare a imaginilor contextualizate. Punctul final al imaginii este următorul:
https://api.flickr.com/services/rest/?format=json&nojsoncallback=1& sort = aleatoare & metodă = flickr.photos.search & tags = mars, planetă, rover & tag_mode = toate & api_key = [YOUR_KEY]
După cum puteți vedea, cererea este destul de simplă. Spuneți Flickr că vă va oferi rezultate formate ca JSON (Format = JSON
), dar nu specificăm un apel JSON (nojsoncallback = 1
). Căutați o imagine (Metoda = flickr.photos.search
) și etichetele care vă interesează sunt legate de Marte (tag-uri = Marte, planeta, rover
). Consultați documentația pentru mai multe informații despre formatul adresei URL a solicitării.
Începeți prin a declara următoarele variabile:
finală statică String FLICKR_API_KEY = "[INSERTAȚI AICI DATĂ API]", IMAGES_API_ENDPOINT = "https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&sort=random&method=flickr.photos.search& Tag-uri" + " = Marte, planeta, rover & tag_mode = all & api_key = ";
Apoi, implementați searchRandomImage
metodă:
căutare privată privatăRandomImage () aruncă excepția if (FLICKR_API_KEY.equals ("")) arunca o nouă excepție ("Nu ați furnizat un API Flickr de lucru!"); Solicitare CustomJsonRequest = CustomJsonRequest nou (Request.Method.GET, IMAGES_API_ENDPOINT + FLICKR_API_KEY, null, new Response.Listener() @Override public void peResponse (răspunsul JSONObject) încercați JSONArray images = response.getJSONObject ("photos") getJSONArray ("photo"); int index = nou Random (). nextInt (images.length ()); JSONObject imageItem = images.getJSONObject (index); String imageUrl = "http: // farm" + imageItem.getString ("ferma") + ".static.flickr.com /" + imageItem.getString ("server" ) + "_" + imageItem.getString ("secret") + "_" + "c.jpg"; // TODO: face ceva cu * imageUrl * captură (Excepție e) imageError (e); , noul Response.ErrorListener () @Override public void peErrorResponse (eroare de eroareVolleyError) imageError (eroare); ); request.setPriority (Request.Priority.LOW); helper.add (cerere);
Dupa cum vedeti, Flickr trimite inapoi a JSONArray
conținând imaginile. Metoda pe care am scris-o pentru a prelua o imagine aleatoare generează un număr aleator între zero și dimensiunea matricei. Acesta ia elementul corespunzător acelui index din matricea de rezultate și construiește adresa URL a imaginii în conformitate cu aceste linii directoare.
Ca și înainte, avem nevoie de o metodă de tratare a erorilor:
int mainColor = Color.parseColor ("# FF5722"); private void imageError (excepție e) mImageView.setBackgroundColor (mainColor); e.printStackTrace ();
În cele din urmă, sună searchRandomImage
în onCreate
și nu uitați să prindeți excepții.
Acum, când avem o adresă URL de încărcat, putem afișa imaginea. Ați învățat deja cum să faceți acest lucru în articolul precedent.
private void loadImg (String imageUrl) // Obține o imagine specificată de adresă URL și o afișează în cererea ImageRequest pentru UI = new ImageRequest (imageUrl, new Response.Listener() @Override public void peResponse (bitmap bitmap) mImageView.setImageBitmap (bitmap); , 0, 0, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, noul Response.ErrorListener () public void onErrorResponse (eroare eroare eroare) imageError (eroare); ); // nu trebuie să setăm prioritatea aici; // ImageRequest vine deja cu // setat la LOW, exact ceea ce avem nevoie. helper.add (cerere);
În onResponse
metoda pe care am scris-o în etapa anterioară, suntem în cele din urmă capabili să tratăm rezultatul.
loadImg (URL a imaginii);
Poate că ați observat deja că ocolim sistemul de caching al lui Volley prin preluarea unei imagini aleatorii de fiecare dată când aplicația este lansată. Trebuie să găsim o modalitate de a afișa aceeași imagine într-o anumită zi.
Cea mai simplă modalitate de a realiza acest lucru este folosirea aplicației Android SharedPreferences
. Începeți prin a declara variabilele de care avem nevoie pentru acest lucru.
SharedPreferences mSharedPref; int astăzi = Calendar.getInstance () get (Calendar.DAY_OF_MONTH); ultimul șir static SHARED_PREFS_IMG_KEY = "img", SHARED_PREFS_DAY_KEY = "zi";
Apoi, în onCreate
înainte de apelul către searchRandomImage
, inițializa mSharedPref
.
mSharedPref = getPreferences (Context.MODE_PRIVATE);
Ideea este să stocăm ziua curentă de fiecare dată când preluăm o nouă imagine aleatorie. Desigur, stocăm URL-ul imaginii alături de zi. Când se lansează aplicația, verificăm dacă avem deja o intrare în SharedPreferences
pentru ziua curentă. Dacă avem un meci, vom folosi adresa URL stocată. În caz contrar, vom prelua o imagine aleatorie și vom stoca adresa URL în SharedPreferences
.
În searchRandomImage
, după definiția lui Imagine URL
, adăugați următoarele rânduri de cod:
// imediat după * String imageUrl = ... * // salvează imaginea zilei SharedPreferences.Editor editor = mSharedPref.edit (); editor.putInt (SHARED_PREFS_DAY_KEY, astăzi); editor.putString (SHARED_PREFS_IMG_KEY, imageUrl); editor.commit (); // și apoi există * loadImage (imageUrl); *
onCreate
după definiție mSharedPref
, acum devine:
dacă (mSharedPref.getInt (SHARED_PREFS_DAY_KEY, 0)! = astăzi) // căutați și încărcați o martor aleator pict try searchRandomImage (); captură (Excepție e) // nu uitați să setați propriul API Flickr! // altfel nu voi putea să arăt // o imagine aleatorie Marte imagineError (e); altceva // avem deja o imagine a zilei: să o încărcăm loadImg (mSharedPref.getString (SHARED_PREFS_IMG_KEY, "")); loadWeatherData ();
Asta e. Cererea dvs. estegata. Simțiți-vă liber să descărcați fișierele sursă ale acestui tutorial pe GitHub pentru a vedea proiectul finalizat. Uitați-vă la proiect, dacă vă confruntați cu probleme.
Fontul utilizat în interfața cu utilizatorul determină de multe ori aspectul unei aplicații. Să începem prin schimbarea fontului implicit Roboto cu un font mai atrăgător, cum ar fi lumina Lato.
Creați un nou dosar numit fonturi în bunuri pliant. Dacă nu găsiți bunuri folder, trebuie să îl creați la același nivel ca și java pliant. Structura folderului ar trebui să arate ceva asemănător app \ src \ principalele active \ \ fonturi.
Copiați fișierul Lato-light.ttf în fonturi pliant. În onCreate
, trebuie să înlocuiți textul prestabilit al vizualizărilor în care doriți să utilizați noul font.
mTxtDegrees.setTypeface (Typeface.createFromAsset (getAssets (), "fonturi / Lato-light.ttf")); mTxtWeather.setTypeface (Typeface.createFromAsset (getAssets (), "fonturi / Lato-light.ttf"));
Urmând liniile directoare pentru Android Material Design, putem face bara de stare transparentă. În acest fel, fundalul va fi parțial vizibil prin bara de stare.
Puteți realiza acest lucru făcând o mică schimbare în tema aplicației. Editați proiectul V21 \ style.xml fișier ca acesta:
Asigurați-vă că AndroidManifest.xml este deja setat să folosească tema:
Am făcut o călătorie lungă. În primul articol, am început să vorbim despre Volley și aplicațiile sale. În acest tutorial, am analizat o modalitate practică de a implementa conceptele pe care le-am învățat construind o aplicație meteorologică pentru Marte. Acum ar trebui să înțelegeți bine biblioteca Volley, cum funcționează și ce puteți folosi pentru ea.