这是Android《第一行代码》第2版中的app项目。代码可参考:https://github.com/guolindev/booksource 。总体上是一个请求网络json格式的天气数据,然后呈现在界面上的一个app项目。架构如下
P.S. 经实际测试,项目中的网络api如今都相应很缓慢了,还是建议寻找新的api。
一、网络请求
要请求的链接有两类,一类返回省、市、区(县)等列表信息,另一类返回某一个区(县)的具体天气信息。均返回的是json数据。第一类链接示例如下:
- http://guolin.tech/api/china (省列表)
- http://guolin.tech/api/china/23 (广东省下的城市列表)
- http://guolin.tech/api/china/23/205 (广州市下的区列表)
第二类链接示例如下:
- http://guolin.tech/api/weather?cityid=CN101280101&key=*** (广州市天气信息,key需申请)
两者请求的都是json数据,采用OKHttp3库来实现网络请求。 与JAVA原生的HttpURLConnection相比,OKHttp3其中一个有点是不用自己新建线程。
二、JSON解析
一种数据是省、市、区(县)等列表信息,结构较简单,如下。这种可直接用系统自带的JSONObject解析。另外,这种格式为列表结构,适合存储到数据库中缓存。
[
{
"id": 1,
"name": "北京"
},
{
"id": 2,
"name": "上海"
},
{
"id": 3,
"name": "天津"
},
......
{
"id": 34,
"name": "新疆"
}
]
另一种是天气详情,格式较为复杂,如下。这里采用GSON映射到实体类的方式解析,并用SharePreferences缓存。
{
"HeWeather": [
{
"basic": {
"cid": "CN101280601",
"location": "深圳",
"parent_city": "深圳",
"admin_area": "广东",
"cnty": "中国",
"lat": "39.12559509",
"lon": "117.19018555",
"tz": "+8.00",
"city": "深圳",
"id": "CN101280601",
"update": {
"loc": "2021-07-08 05:55",
"utc": "2021-07-08 05:55"
}
},
"update": {
"loc": "2021-07-08 05:55",
"utc": "2021-07-08 05:55"
},
"status": "ok",
"now": {
"cloud": "91",
"cond_code": "104",
"cond_txt": "阴",
"fl": "10",
"hum": "27",
"pcpn": "0.0",
"pres": "1014",
"tmp": "13",
"vis": "24",
"wind_deg": "194",
"wind_dir": "西南风",
"wind_sc": "2",
"wind_spd": "11",
"cond": {
"code": "104",
"txt": "阴"
}
},
"daily_forecast": [
{
"date": "2021-07-09",
"cond": {
"txt_d": "阵雨"
},
"tmp": {
"max": "12",
"min": "6"
}
},
{
"date": "2021-07-10",
"cond": {
"txt_d": "晴"
},
"tmp": {
"max": "13",
"min": "4"
}
},
{
"date": "2021-07-11",
"cond": {
"txt_d": "晴"
},
"tmp": {
"max": "15",
"min": "5"
}
}
],
"aqi": {
"city": {
"aqi": "47",
"pm25": "30",
"qlty": "优"
}
},
"suggestion": {
"comf": {
"type": "comf",
"brf": "较舒适",
"txt": "白天会有降雨,这种天气条件下,人们会感到有些凉意,但大部分人完全可以接受。"
},
"sport": {
"type": "sport",
"brf": "较不宜",
"txt": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意保暖并携带雨具。"
},
"cw": {
"type": "cw",
"brf": "不宜",
"txt": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
}
},
"msg": "所有天气数据均为模拟数据,仅用作学习目的使用,请勿当作真实的天气预报软件来使用。"
}
]
}
三、数据存储
对于省、市、区(县)等列表信息,第一次请求时从网络获取;随后存到数据库。后续访问优先从数据库获取。数据库使用litepal库,与直接原生操作SQLite相比,litepal采用对象关系映射(ORM)模式,提升了开发效率。
对于天气数据,则直接将json数据存储到SharePreferences中。下次打开app时,优先访问SharePreferences缓存的内容,再对json数据解析,然后呈现到界面上。
四、界面
界面分两部分,一个是显示省、市、区(县)等列表信息的界面,另一个是显示天气信息的详细界面。
显示省、市、区(县)等列表信息的界面如下。第一次启动app,会进入到这个城市选择列表。另外,在天气信息界面,也可以打开侧滑栏,重新选择城市。
实现上,城市列表用ListView,载体为Fragment。使用Fragment的好处在于,可以复用该列表界面,同时嵌入在MainActivity和侧滑栏当中。
而天气界面,则由RelativeLayout和LinearLayout等布局组合完成。值得一提的是,下拉更新采用SwipeRefreshLayout组件实现,侧滑栏使用DrawerLayout组件实现。