Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Android SDK
Code

使用Volley创建一个火星天气应用

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called An Introduction to Volley.
An Introduction to Volley

Chinese (Simplified) (中文(简体)) translation by Hejie Jiang (you can also view the original English article)

Final product image
What You'll Be Creating

介绍

在这篇文章中,我会演示一个从前一篇文章 中学到的有关Volley的使用案例。 我们将创建一个火星天气的应用,使用{MAAS} API公开的探索者号搜集的数据。

首先,我们在Android Studio中配置好项目,并设计好用户界面。 然后使用Volley完成应用的核心部分。 因为每个漂亮的应用往往都有一些特色图片,所以我将演示如何使用 Flickr的api获取一张随机图片。 我们将使用Volley来下载图片,主要是考虑到其强大的缓存系统。 最后我们将添加一些漂亮的细节让app看起来 更美观。

1. 项目设置

首先,在Android Studio中创建一个新的项目。 因为Volley是向后兼容的,所以你可以选择任意级别的api。 我选择的是API 21,不过只要api在8(Froyo) 以上应该都是很ok的。

第一步: 用户界面

我们的应用只有一个简单的Activity。 直接使用Android Studio建议的MainActivity.java。 打开布局编辑器,双击activity_main.xml。

因为屏幕70%的范围都被图片占用,剩下的部分是天气信息,所以我们要使用xml的layout_weight属性。 你当然也可以使用绝对值,但是不同的 设备值是不同的。 如果使用一个绝对的值,在很小的设备上图像可能是90-10的比率,在较大的设备上可能是70-30甚至60-40的比率。 而 layout_weight属性可以解决这个问题。

在里面的第一个child中,添加ImageView:

在第二个RelativeLayout中,我们添加了几个TextView元素。 其中两个分别显示平均温度与天气状态。 第三个是显示错误信息的标签。

现在布局已经完成了。 如果你愿意,可以自己添加更多的详细信息,但是复杂和详细的用户界面并不在本教程的范围之内。

第二步: 主题和权限

在开始深入应用的核心功能之前,还要先处理两个事情。 1.将继承的主题改成android:Theme.Material.Light.NoActionBar, 这样我们就不必在运行时隐藏actionbar。

2.在项目的manifest中添加网络权限。

2. 应用核心

第一步: 导入Volley

正如我在上篇文章中讲述的,使用Volley最简单且可靠的方式是将library作为一个module导入。 下载library的 源代码 ,通过File > New > Module将其导入,然后在 build.gradle文件中告诉compiler把它包含在项目中。

第二步: 实现帮助类

上篇文章  我们已经指出了,如果你想发起多个请求,最好使用共享的请求队列, 要避免每次布置一个请求都使用Volley.newRequestQueue来创建一个新的队列,因为我们不想看到内存泄漏或者其他的问题发生。

为 了达到这个目的,你首先需要创建一个使用了单例模式的类。 这个类被作为静态的,全局的对象引用,然后由它处理RequestQueue对象。 这样,整个应 用中就只有一个RequestQueue。 接下来,继承Application类,你需要告诉系统在应用启动的时候创建这个对象,这个过程甚至发生在第一 个Activity创建之前。

因为我们是在安卓系统中,所以我们要简单的修改一下常规单例模式的结构。 这个类需要在 Application.onCreate方法中创建一个自己的实例 - 而不是在常规的getInstance方法中判断它为null的时候产生一个实例。

为此,我们创建一个继承自Application类的 MarsWeather.java类, 重写onCreate方法,初始化这个静态实例的RequestQueue对象,

在这个单例类中,我们使用一个公共的synchronized方法 getInstance来构造类的对象。 在getInstance方法内部,返回一个mInstance变量。 onCreate是在应用启动的时候触发, 因此mInstance变量在getInstance方法被调用的第一时间就已经设置好了。

接下来,在AndroidManifest.xml文件中告诉系统你想让MarsWeather在应用启动的时候被加载, 在application标签下,如下添加属性名称:

好了, 一个Application类的实例就创建好了,它甚至要比MainActivity都要先创建。 除了那些标准的操作,比如调用 super.onCreate,onCreate还产生了一个RequestQueue的实例。

除此之外,我们还需要实现另外三个方法才能完成这个帮助 类。 第一个方法是getRequestQueue,替代了Volley.newRequestQueue,直接返回在onCreate中实例化了的 mRequestQueue。 我们还需要一个添加请求到队列的方法add,以及负责取消请求的方法cancel。 这三个方法实现如下:

TAG是一个用于识别请求的标记。 在这个例子中,可以是任意值:

第三步: 实现自定义的Request

正如你已经知道的,Volley提供了三种标准的请求类型:StringRequest, ImageRequest, 和 JsonRequest。 我们的应用将使用后那两个去获取天气数据和随机图片列表。

默认情况下,Volley将请求的优先级设置为普通。 一般这也没什么问题,然而在我们的应用 中,两种请求的差别很大,有必要让它们在队列中有不同的优先级。 获取天气数据的优先级要比获取随机图片的高。

因此我们需要自定义JsonRequest 类。 创建一个继承自JsonObjectRequest的CustomJsonRequest.java, 然后如下重写getPriority方法。

第四步: 获取数据

接下来总轮到算到了教程最有趣的部分-获取天气数据, 请求的后端地址是:

这个api是可以直接浏览的,那我们打开这个链接查看返回的JSON结果。 这个JSON包含了一个简单的数据对象,由一些列的字符串组成,从温度到风向以及日落时间。

我们首先在MainActivity class中声明以下的变量:

你可以在onCreate之外调用MarsWeather.getInstance。 既然这个类早就初始化了,你也就不必等到onStart方法执行的时候才调用它。 当然界面中的view还是需要在onCreate方法中引用。

完成这些工作之后,我们开始实现loadWeatherData方法。 。我们创建了一个自定义的Volley请求并设置优先级为高。 然后我们调用了帮助类的add方法将请求添加进队列中。 最重要的其实是result listener部分,因为它将关系到用户界面。

你可以看到,这个方法获取了最低和最高温度,计算了平均温度,然后用它们更新了用户界面。 我还实现了一个处理错误的简单方法。

我们现在只需要在onCreat中调用已经完成的loadWeatherData方法, app现在已经可以显示来自火星上的天气数据了。

3. 获取图片数据

既然已经完成了app的核心部分,那么我可以考虑如何让app看起来更吸引人一些。 可以随机的获取一张火星图片,然后显示给用户。

第一步: 获取一张随机的图片

你需要一个Flickr API key来获取一组随机图片。 图片的后端地址是:

可以看到,这个请求非常简单。 你可以告诉Flickr给你一个JSON格式的结果(format=json),但是我们并不会指定一个JSON callback(nojsoncallback=1)。 你是要搜索一张图片(method=flickr.photos.search), 并且感兴趣的是和火星相关的标签(tags=mars,planet,rover)。 可以查阅documentation 以了解关于请求URL格式的更多信息。

声明如下变量:

接下来实现searchRandomImage方法:

可以看到Flickr发送回了一个包含图片的JSONArray。 在这个方法中我产生了一个在0和数组大小之间的随机数字,以随机的从图片数组中获取一张图片。 从数组的索引中获取相应的item然后根据这些指导构造一个图片的URL。

跟前面一样,我们需要一个处理错误的方法:

最后,在onCreate中调用searchRandomImage,别忘记捕获可能出现的异常。

第二步: 显示图片

我们已经有了待加载的URL,可以开始显示图片了。 从前面的文章中,你已经学会了该如何做。

在onResponse方法中我们写入前一步的东西,总算可以处理结果了。

第三步: 每天显示一张新的图片

你可能已经注意到我们在应用每次启动的时候获取一张随机图片,绕过了Volley的缓存机制。 需要想办法在一天中只显示同一张图片。

最简单的办法就是使用安卓的SharedPreferences, 先从声明所需的变量开始:

接下来,在onCreate方法中,在调用searchRandomImage之前初始化mSharedPref。

思路是在每次获取一张新的随机图片的时候都保存当天的日期(其实保存的是某月的第几天)。 当然,我们还同时保存了该天图片的URL。 当应用启动的时候,我 们检查在SharedPreferences中是否有当天的入口, 如果已经有匹配,我们使用保存了的URL, 反之获取一张随机的图片,并在 SharedPreferences中保存下URL。

相关的代码是在searchRandomImage方法中,在定义完imageUrl之后,添加如下的代码:

然后在onCreate方法中,mSharedPref定义之后的代码就变成了:

好了, 应用已经完成, 可以在GitHub上免费下载本教程的完整源码。 如果在这篇文章中遇到什么问题可以参考完整的源码。

小提示: 改善用户界面

第一步: 字体

用户界面中的字体决定了一个应用的直观感受。 我们先从改变默认的Roboto字体开始,用更好看的字体来替代,比如 Lato light。

在assets文件夹下创建一个名叫fonts的文件夹。 如果你没找到assets文件夹,你需要在java文件夹的同一级目录下创建一个。 文件夹的结构差不多是这样:app\src\main\assets\fonts。

将Lato-light.ttf拷贝到fonts文件夹中。 在 onCreate方法中你需要重写那些想使用新字体的View的默认typeface。

第二步: 透明的Status Bar

根据安卓Material Design的规范,我们可以是状态栏透明, 这样背景就可以透过状态栏部分可见。

你可以通过应用主题的一点小小改动达到此目的。 如下编辑v21\style.xml:

确保AndroidManifest.xml已经设置成使用这个主题:

总结

我们完成了一个漫长的旅程。 在第一篇文章中,我们讨论了Volley以及应用。 这篇教程中,我们通过创建一个火星天气应用来实践了所学的基本知识。 你应该对Volley库及其应用范围都有了良好的认识。

关注我们的公众号
Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.