Dans ce tutoriel, je vais vous montrer un cas d'utilisation possible de ce que nous avons appris dans le précédent article sur Volley. Nous allons créer une application météo pour Mars, en utilisant les informations collectées par le mobile Curiosity, mises à la disposition de tous par la NASA via l'API MAAS..
Tout d'abord, nous allons configurer le projet dans Android Studio et concevoir l'interface utilisateur. Nous structurerons ensuite le noyau de l'application à l'aide de Volley. Comme chaque belle application contient des images, je vais vous montrer comment en récupérer une au hasard en utilisant l'API de Flickr. Nous allons télécharger la photo avec Volley, principalement à cause de son excellent système de mise en cache. Enfin, nous ajouterons quelques détails sophistiqués pour donner à l'application un aspect et une sensation magnifiques..
Tout d'abord, créez un nouveau projet dans Android Studio. Puisque Volley est compatible avec les versions antérieures, vous pouvez choisir le niveau d’API que vous préférez. J'ai opté pour l'API 21, mais ça devrait aller tant que le niveau de l'API est de 8 (Froyo) ou supérieur..
Notre application a une seule activité simple. Vous pouvez l'appeler MainActivity.java, comme suggéré par Android Studio. Ouvrez l'éditeur de disposition et double-cliquez sur activity_main.xml.
Puisque nous aimerions avoir environ 70% de l'écran dédié à l'image et le reste aux informations météorologiques, nous devons utiliser l'attribut XML. layout_weight
. Bien sûr, nous pouvons aussi utiliser des valeurs absolues, mais ce ne serait pas la même chose. Malheureusement, le monde Android propose des affichages qui ne sont pas homogènes, et spécifier une valeur absolue pour la hauteur de l’image peut donner un rapport 90-10 sur de très petits appareils et une relation 70-30, voire 60-40 sur des appareils plus grands. le layout_weight
attribut est ce dont vous avez besoin pour résoudre ce problème.
Dans le premier enfant, ajoutez le ImageView
:
Dans la seconde Disposition relative
, nous ajoutons une liste de Affichage
articles. Deux d’entre elles sont des vues dans lesquelles la température moyenne et l’opacité de l’atmosphère sont affichées. Le troisième est une étiquette d'erreur.
La mise en page devrait maintenant être complète. Vous pouvez ajouter plus de détails si vous le souhaitez, mais une interface utilisateur complexe et détaillée ne fait pas partie de ce didacticiel..
Nous devons nous occuper de deux autres choses avant de commencer à creuser le cœur de l'application. Changez le thème hérité de l'application en android: Theme.Material.Light.NoActionBar
. Cela signifie que nous n'avons pas besoin de cacher la barre d'action au moment de l'exécution.
Enfin, ajoutez l'autorisation Internet au manifeste du projet..
Comme nous l'avons vu dans l'article précédent, le moyen le plus simple et le plus fiable d'utiliser Volley consiste à importer la bibliothèque en tant que nouveau module. Téléchargez le code source de la bibliothèque, importez-le via Fichier > Nouveau > Module, et dire au compilateur dans le projet build.gradle fichier pour l'inclure dans le projet.
compiler le projet (": volley")
Comme je l'ai déjà souligné dans l'article précédent, si vous devez déclencher plusieurs demandes, il est préférable d'utiliser une file d'attente de demandes partagées. Vous devez éviter de créer une file d’attente chaque fois que vous planifiez une demande en appelant Volley.newRequestQueue
, parce que vous ne voulez pas vous retrouver avec des fuites de mémoire et d'autres problèmes indésirables.
Pour ce faire, vous devez d’abord créer une classe en utilisant le modèle singleton. La classe est référencée à l'aide d'une variable statique, globalement visible, qui gère ensuite l'objet. RequestQueue
. De cette façon, vous vous retrouvez avec un seul RequestQueue
pour l'application. Puis, étendant le Application
classe, vous devez demander au système d’exploitation de générer cet objet au démarrage de l’application, même avant la création de la première activité.
Comme nous sommes dans l’environnement Android, nous modifions légèrement la structure commune du singleton. La classe doit créer une nouvelle instance de lui-même dans le Application.onCreate
méthode-pas dans un générique getInstance
méthode quand il est nul
.
Pour ce faire, créez une nouvelle classe et nommez-la. MarsWeather.java. Ensuite, étendre l'Android Application
classe, remplace le onCreate
méthode et initialiser le RequestQueue
objet de l'instance statique.
Dans la classe singleton, nous construisons l'objet de la classe en utilisant un Publique
et synchronisé
une fonction getInstance
. Dans cette méthode, nous retournons le mInstance
variable. le onCreate
La méthode est invoquée au démarrage de l'application pour que le mInstance
variable sera déjà définie la première fois le getInstance
la méthode est invoquée.
Classe publique MarsWeather étend Application private RequestQueue mRequestQueue; mInstance statique privée de MarsWeather; @Override public void onCreate () super.onCreate (); mInstance = this; mRequestQueue = Volley.newRequestQueue (getApplicationContext ()); public statique synchronisé MarsWeather getInstance () return mInstance;
Ensuite, racontez dans le AndroidManifest.xml fichier que vous voulez MarsWeather
être chargé au démarrage de l'application. dans le
tag, ajouter l'attribut prénom
comme suit:
android: name = ". MarsWeather"
C'est tout. Un exemple de Application
la classe est créée, même avant Activité principale
est créé. Avec toutes les autres opérations standard, onCreate
génère une instance du RequestQueue
.
Nous devons implémenter trois autres méthodes pour terminer la classe d'assistance. La première méthode remplace Volley.newRequestQueue
, que je nommerai getRequestQueue
. Nous avons également besoin d'une méthode pour ajouter une demande à la file d'attente, ajouter
, et une méthode responsable de l'annulation des demandes, Annuler
. Le bloc de code suivant montre à quoi ressemble l'implémentation.
public RequestQueue getRequestQueue () return mRequestQueue; Publiquevoid add (Request req) req.setTag (TAG); getRequestQueue (). add (req); public void cancel () mRequestQueue.cancelAll (TAG);
ÉTIQUETTE
est un jeton générique que vous utilisez pour identifier la demande. Dans ce cas précis, cela peut être ce que vous voulez:
public static final String TAG = MarsWeather.class.getName ();
Comme vous le savez déjà, Volley fournit trois types de demandes standard: StringRequest
, ImageRequest
, et JsonRequest
. Notre application va utiliser ce dernier pour récupérer des données météorologiques et récupérer la liste des images aléatoires.
Par défaut, Volley définit la priorité de la demande sur ORDINAIRE
. En règle générale, ce serait bien, mais dans notre application, nous avons deux demandes très différentes et nous devons donc avoir une priorité différente dans la file d'attente. La récupération des données météorologiques doit avoir une priorité supérieure à celle de l'URL de l'image aléatoire..
Pour cette raison, nous devons personnaliser le JsonRequest
classe. Créer une nouvelle classe nommée CustomJsonRequest.java, et assurez-vous qu'il se prolonge JsonObjectRequest
. Ensuite, remplacez le obtenir la priorité
méthode comme indiqué ci-dessous.
Classe publique CustomJsonRequest étend JsonObjectRequest public CustomJsonRequest (méthode int, URL de chaîne, JSONObject jsonRequest, Response.Listenerécouteur, Response.ErrorListener errorListener) super (méthode, url, jsonRequest, écouteur, errorListener); priorité privée mPriority; public void setPriority (priorité prioritaire) mPriority = priorité; @Override public Priority getPriority () return mPriority == null? Priority.NORMAL: mPriority;
Nous sommes enfin arrivés à la partie la plus intéressante de ce tutoriel dans laquelle nous écrivons l'implémentation pour récupérer les données météorologiques. Le noeud final de la demande est:
http://marsweather.ingenology.com/v1/latest/
Les API sont navigables, alors ouvrez le lien pour inspecter le JSON résultant. Le JSON contient un objet simple, résultat
, qui comprend une série de chaînes, allant de la température à la direction du vent et au coucher du soleil.
Commencez par déclarer les variables suivantes dans le Activité principale
classe:
TextView mTxtDegrees, mTxtWeather, mTxtError; Aide MarsWeather = MarsWeather.getInstance (); chaîne statique finale RECENT_API_ENDPOINT = "http://marsweather.ingenology.com/v1/latest/";
Tu peux appeler MarsWeather.getInstance
en dehors de onCreate
. Comme la classe sera déjà initialisée, vous n’avez pas besoin d’attendre le onStart
méthode pour l'appeler. Bien sûr, vous devez définir les références des vues de l'interface utilisateur dansla onCreate
méthode.
mTxtDegrees = (TextView) findViewById (R.id.degrees); mTxtWeather = (TextView) findViewById (R.id.weather); mTxtError = (TextView) findViewById (R.id.error);
Après cela, il est temps de mettre en œuvre le loadWeatherData
méthode. Nous créons une demande Volley personnalisée et définissons la priorité sur HAUTE
. Nous invoquons ensuite l'assistant ajouter
méthode pour l'ajouter à la file d'attente des demandes. La chose importante à noter est l'écouteur de résultat, car cela affectera l'interface utilisateur..
private void loadWeatherData () CustomJsonRequest request = new CustomJsonRequest (Request.Method.GET, RECENT_API_ENDPOINT, null, nouveau Response.Listener() @Override public void onResponse (réponse JSONObject) try String minTemp, maxTemp, atmo; int avgTemp; response = response.getJSONObject ("report"); minTemp = response.getString ("min_temp"); minTemp = minTemp 3 (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); , new Response.ErrorListener () @Override public void onErrorResponse (erreur VolleyError) txtError (error); ); request.setPriority (Request.Priority.HIGH); helper.add (demande);
Comme vous pouvez le constater, la méthode prend les températures minimale et maximale, calcule la température moyenne et met à jour l'interface utilisateur. J'ai également implémenté une méthode simple pour gérer les erreurs.
private void txtError (Exception e) mTxtError.setVisibility (View.VISIBLE); e.printStackTrace ();
Nous n'avons plus qu'à appeler loadWeatherData
dans onCreate
et tu as fini. L'application est maintenant prête à afficher la météo de Mars.
Maintenant que le cœur de l'application est prêt et opérationnel, nous pouvons nous concentrer pour rendre l'application plus attrayante sur le plan visuel. Nous allons faire cela en récupérant une image aléatoire de Mars et en l'affichant à l'utilisateur.
Vous aurez besoin d’une clé d’API Flickr pour extraire une liste aléatoire d’images contextualisées. Le point final de l'image est le suivant:
https://api.flickr.com/services/rest/?format=json&nojsoncallback=1& sort = aléatoire & méthode = flickr.photos.search & tags = mars, planète, mobile & tag_mode = all & api_key = [VOTRE_KEY]
Comme vous pouvez le constater, la demande est assez simple. Vous dites à Flickr de vous donner des résultats au format JSON (format = json
), mais nous ne spécifions pas de rappel JSON (nojsoncallback = 1
). Vous recherchez une image (méthode = flickr.photos.search
) et les tags qui vous intéressent sont liés à Mars (tags = mars, planète, rover
). Consultez la documentation pour plus d'informations sur le format de l'URL de la demande..
Commencez par déclarer les variables suivantes:
final static String FLICKR_API_KEY = "[INSERER ICI VOTRE CLE D'API]", IMAGES_API_ENDPOINT = "https://api.flickr.com/services/rest/?format=json&nojsoncallback=1&sort=random&method=flickr.photos.search&" "tags = mars, planète, mobile & tag_mode = all & api_key = ";
Ensuite, implémentez le searchRandomImage
méthode:
void privé searchRandomImage () lève une exception if (FLICKR_API_KEY.equals ("")) jette une nouvelle exception ("Vous n'avez pas fourni une API Flickr fonctionnelle!"); CustomJsonRequest request = new CustomJsonRequest (Request.Method.GET, IMAGES_API_ENDPOINT + FLICKR_API_KEY, null, nouveau Response.Listener() @Override public void onResponse (réponse JSONObject) try JSONArray images = response.getJSONObject ("photos"). GetJSONArray ("photo"); int index = new Random (). nextInt (images.length ()); JSONObject imageItem = images.getJSONObject (index); String imageUrl = "http: // batterie" + imageItem.getString ("batterie") + ".static.flickr.com /" + imageItem.getString ("serveur") + "/" + imageItem.getString ("id" ) + "_" + imageItem.getString ("secret") + "_" + "c.jpg"; // TODO: faire quelque chose avec * imageUrl * catch (exception e) imageError (e); , new Response.ErrorListener () @Override public void onErrorResponse (erreur VolleyError) imageError (error); ); request.setPriority (Request.Priority.LOW); helper.add (demande);
Comme vous pouvez le constater, Flickr renvoie un JSONArray
contenant les images. La méthode que j'ai écrite pour récupérer une image aléatoire génère un nombre aléatoire compris entre zéro et la taille du tableau. Il extrait l'élément correspondant à cet index du tableau de résultats et construit l'URL de l'image en suivant ces instructions..
Comme auparavant, nous avons besoin d’une méthode de traitement des erreurs:
int mainColor = Color.parseColor ("# FF5722"); private void imageError (Exception e) mImageView.setBackgroundColor (mainColor); e.printStackTrace ();
Enfin, appelez searchRandomImage
dans le onCreate
méthode et ne pas oublier d'attraper des exceptions.
Maintenant que nous avons une URL à charger, nous pouvons afficher la photo. Vous avez déjà appris comment faire cela dans l'article précédent.
private void loadImg (String imageUrl) // Récupère une image spécifiée par l'URL et l'affiche dans la demande d'interface utilisateur ImageRequest request = new ImageRequest (imageUrl, new Response.Listener() @Override public void onResponse (bitmap bitmap) mImageView.setImageBitmap (bitmap); , 0, 0, ImageView.ScaleType.CENTER_CROP, Bitmap.Config.ARGB_8888, new Response.ErrorListener () public void onErrorResponse (erreur VolleyError) imageError (error); ); // nous n'avons pas besoin de définir la priorité ici; // ImageRequest arrive déjà avec // priorité définie sur LOW, c'est exactement ce dont nous avons besoin. helper.add (demande);
dans le onResponse
méthode que nous avons écrite à l'étape précédente, nous sommes enfin capables de gérer le résultat.
loadImg (imageUrl);
Peut-être avez-vous déjà remarqué que nous évitons le système de cache de Volley en récupérant une image aléatoire chaque fois que l'application est lancée. Nous devons trouver un moyen de montrer la même image un jour donné.
Le moyen le plus simple d'y parvenir est d'utiliser Android Préférences partagées
. Commencez par déclarer les variables dont nous aurons besoin pour cela.
SharedPreferences mSharedPref; int today = Calendar.getInstance (). get (Calendar.DAY_OF_MONTH); chaîne statique finale SHARED_PREFS_IMG_KEY = "img", SHARED_PREFS_DAY_KEY = "jour";
Ensuite, dans le onCreate
méthode, avant l'appel à searchRandomImage
, initialiser mSharedPref
.
mSharedPref = getPreferences (Context.MODE_PRIVATE);
L'idée est de stocker le jour actuel chaque fois que nous récupérons une nouvelle image aléatoire. Bien sûr, nous stockons l'URL de l'image en même temps que la journée. Lorsque l'application démarre, nous vérifions si nous avons déjà une entrée dans le Préférences partagées
pour le jour actuel. Si nous avons une correspondance, nous utilisons l'URL stockée. Sinon, nous récupérons une image aléatoire et stockons son URL dans le répertoire Préférences partagées
.
Dans searchRandomImage
, après la définition de URL de l'image
, ajoutez les lignes de code suivantes:
// juste après * String imageUrl =… * // stocke la photo du jour SharedPreferences.Editor editor = mSharedPref.edit (); editor.putInt (SHARED_PREFS_DAY_KEY, aujourd'hui); editor.putString (SHARED_PREFS_IMG_KEY, imageUrl); editor.commit (); // et puis il y a * loadImage (imageUrl); *
le onCreate
méthode, après la définition du mSharedPref
, devient maintenant:
if (mSharedPref.getInt (SHARED_PREFS_DAY_KEY, 0)! = aujourd'hui) // recherche et charge une image aléatoire de type mars try searchRandomImage (); catch (Exception e) // n'oubliez pas de définir votre propre API Flickr! // sinon je ne pourrai pas montrer // une image aléatoire de Mars imageError (e); else // nous avons déjà une image du jour: chargeons-la loadImg (mSharedPref.getString (SHARED_PREFS_IMG_KEY, "")); loadWeatherData ();
C'est tout. Votre application estprêt. N'hésitez pas à télécharger les fichiers sources de ce tutoriel sur GitHub pour voir le projet terminé. Jetez un coup d'œil au projet si vous rencontrez des problèmes.
La police utilisée dans une interface utilisateur détermine souvent l'aspect et la convivialité d'une application. Commençons par changer la police par défaut Roboto par une police plus attrayante, telle que Lato light..
Créez un nouveau dossier nommé les polices dans le les atouts dossier. Si vous ne trouvez pas le les atouts dossier, vous devez le créer au même niveau que le Java dossier. La structure du dossier devrait ressembler à quelque chose comme app \ src \ main \ actifs \ polices.
Copier le fichier Lato-light.ttf dans le les polices dossier. dans le onCreate
méthode, vous devez remplacer la police de caractères par défaut des vues dans lesquelles vous souhaitez utiliser la nouvelle police..
mTxtDegrees.setTypeface (Typeface.createFromAsset (getAssets (), "fonts / Lato-light.ttf")); mTxtWeather.setTypeface (Typeface.createFromAsset (getAssets (), "fonts / Lato-light.ttf"));
En suivant les instructions pour Android Material Design, nous pouvons rendre la barre d'état transparente. De cette façon, l'arrière-plan sera partiellement visible à travers la barre d'état.
Vous pouvez y parvenir en modifiant légèrement le thème de l'application. Editer le projet v21 \ style.xml fichier comme ceci:
Assurez-vous que le AndroidManifest.xml est déjà configuré pour utiliser le thème:
Nous avons fait un long voyage. Dans le premier article, nous avons commencé à parler de Volley et de ses applications. Dans ce didacticiel, nous avons étudié un moyen pratique de mettre en œuvre les concepts appris en construisant une application météorologique pour Mars. Vous devriez maintenant avoir une bonne compréhension de la bibliothèque Volley, de son fonctionnement et de ce que vous pouvez utiliser pour.