天气查询功能包括信息显示和地区选择两个版块,二者均通过调用极速数据的相关接口进行实现。其中,信息显示界面作为软件首页,默认先显示系统设置的地区天气情况,用户可通过地区选择的界面进行修改信息。对于天气信息,受接口调用次数限制,系统设置每24小时更新一次。具体操作流程如下图所示。
第一节 天气信息显示
该项使用的是极速数据的天气预报接口,利用接口获取指定地区当天信息(设计中显示的是日期、当前温度、最高温、最低温、城市名、星期、风向、天气、更新时间)以及未来四天天气相关情况(设计中显示的是日期、最高温、最低温、天气),之后将获取信息传递给界面进行显示,不同的天气界面会通过变化图标进行表示。
首先,在MainActivity中声明并初始化控件,以便将获取到的天气信息传入界面显示。并设置访问地址url,以便调用API。
(1)信息读取
如图3-1所示,在MainActivity中实现访问网络的内部类。利用AsyncTask可以在处理耗时任务的同时去更新UI的特点,让Getweather对其进行继承从而在该类中可以通过接口实现UI的进度更新,最后将访问结果反馈给UI主线程。代码中实现的是AsyncTask中的onPreExecute()、doInBackground()两个函数,此外,还定义了openConnection()函数。其中,doInBackground()为抽象函数在AsyncTask中必须实现,此处用于在后台将参数地址(params[0])、城市Id(params[1])传递给openConnection并调用其,从而开始查询目标城市信息。
图 3- 1获取天气信息的内部类Getweather
openConnection()函数代码如图3-2所示,在开发中用的网络请求是标准Java接口HttpURLConnectio中的get请求方式。由于URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号,而从doInBackground()传来的参数中包含汉字,所以首先需要利用URLEncoder.encode()方法进行转码。然后获取连接对象并设置请求方式,连接进行查询之后得到包含天气信息的响应流。再利用BufferedReader类采用readLine()方式将获得的字符输入流(即响应流)转为文本,输出天气信息。
图 3- 2 openConnection()函数
onPreExecute()函数中,将openConnection()中访问得到的result作为参数传入,此时得到的是JSON数据。首先先将数据转为JSONObject形式。由于JSONObject是一个对象,JSONArray是一个数组,再结合极速数据官方给出的API调用文档可知,获取当天天气信息时,同一天的各天气信息可以看作独立个体,分别存储在“today”中,所以获取当天信息应使用JSONObject,如图3-3所示。
图 3- 3onPreExecute()函数中获取当天天气信息
而对于未来天气,应先将同一天的所有天气信息作为一个整体看待(即先将所有天气信息按日期进行分类,所属日期相同的天气信息属于同一类),分类之后多个这样的整体储存在“forecast”之中构成数组,最后再分别从各个整体中读取相应信息。所以读取未来天气情况时,应先使用JSONArray让未来几天天气情况以日期为界限进行划分,共同构成一个数组,数组中第1—4个元素分别为未来第1—4天,之后再用JSONObject读取数组中每个元素其中包含的详细天气信息,如图3-4所示。
图 3- 4 onPreExecute()函数中获取未来天气信息
完成访问网络的内部类编写之后,在onCreate()中添加图3-5代码开启网络访问活动,自此实现在有默认地点情况下,天气预报信息的查询与传递。
图 3- 5访问天气信息指令
(2)图标更换
天气情况的显示除了文字方式,设计中还添加了图片方式。以当天天气信息显示情况为例,如图3-6所示,利用switch()语句以获取到的weather(晴、多云等)为判断依据,不同的weather值则执行不同指令,在各指令中会借助setImageResource将对应控件(nowView)的图片进行更换。未来四天天气图标的变化方式与此大致相同。
图 3- 6天气图标变化