最近总是有人来和我说我以前写的一个小app无法正常获取数据~Android简易版天气预报app
今天就又运行了下来查找问题,发现或许是接口有限制吧,不能在多台手机使用同个apikey
然后,发现了我写的代码实在乱七八糟,界面也实在不好看,就又重写了一遍,小小地修改了一遍,开发环境改为了Android Studio
最终效果图如下
工程图如下
一、获取地区信息
做这么一个天气预报app,首先就要获取到国内地区列表
(在我的另一篇博客有介绍:向任意网址发起数据请求)
中国天气网开放有天气预报接口,访问“http://www.weather.com.cn/data/list3/city.xml”就可以获取到国内省份列表以及其代号了
如果想要获取广东省下的城市列表,由上图可知广东省的代号为28,则接口地址是 “http://www.weather.com.cn/data/list3/city28.xml”,获取到的城市列表及代号如下:
依次类推还可以获取到更加详细的地区信息,这样就完成了开头部分
二、天气信息的获取
百度的APIStore拥有丰富的接口,涵盖了生活的许多方面。例如,我们就可以通过APIStore的某个接口获取到含有天气信息的JSON数据,从而实现天气预报功能
(在我的另一篇博客有介绍:获取含天气信息的JSON数据)
首先,使用者要有一个百度账号,然后登陆以下网址:中国和世界天气预报
该接口是免费的,不过因此也就不够稳定,我在调试的时候就经常出错
然后在API选项下点击“您自己的apikey”,查看自己的apikey。该值是每个开发者和app的唯一标识,需要妥善保管,有了apikey才可以进行下一步的操作
获取到的天气信息是JSON格式的,需要在程序中再来解析
三、数据库的设计
地区列表这些信息一般都是固定不变的,所以我们可以把第一次联网获取到的数据存进数据库里,下次再次访问时就从数据库里读取即可
首先要设定四个Model,包括:省份、城市、县、每小时天气预测,用来承载数据
每个Model包括几个属性以及相应的get和set方法
例如,省份Province的设计如下所示,城市City和县County的设计类似
/**
* 省份
*/
public class Province {
//省份名
private String provinceName;
//省份ID
private String provinceId;
public String getProvinceId() {
return provinceId;
}
public String getProvinceName() {
return provinceName;
}
public void setProvinceId(String provinceId) {
this.provinceId = provinceId;
}
public void setProvinceName(String provinceName) {
this.provinceName = provinceName;
}
}
每小时天气预测HourlyWeather的设计如下:
/**
* Created by ZY on 2016/7/21.
*/
public class HourlyWeather {
//预测时间
private String time;
//温度
private String temp;
//降水概率
private String pop;
//风力
private String wind;
public HourlyWeather(String time, String temp, String pop, String wind) {
this.time = time;
this.temp = temp;
this.pop = pop;
this.wind = wind;
}
public String getTime() {
return time;
}
public String getTemp() {
return temp;
}
public String getPop() {
return pop;
}
public String getWind() {
return wind;
}
}
然后,新建一个DatabaseHelper类继承于SQLiteOpenHelper,用来建立三个数据库表
public class DatabaseHelper extends SQLiteOpenHelper {
private final String CREATE_PROVINCE = "create table Province ("
+ "provinceName text," + "provinceId text )";
private final String CREATE_CITY = "create table City("
+ "cityName text," + "cityId text," + "provinceId text)";
private final String CREATE_COUNTY = "create table County("
+ "countyName text," + "countyId text," + "cityId text)";
public DatabaseHelper(Context context, String DbName,
CursorFactory factory, int version) {
super(context, DbName, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_PROVINCE);
db.execSQL(CREATE_CITY);
db.execSQL(CREATE_COUNTY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
然后,再建立一个WeatherDB类,用来进行实际的数据库操作,包括存取省份信息、城市信息、县信息等
需要注意的是,因为每个城市都是包含在某个省份下的,所以查询某个省份下的所有城市列表,需要将省份的ID传入作为唯一标识
public class WeatherDB {
private final String DataBaseName = "ZyWeather";
private final int VERSION = 1;
private SQLiteDatabase database;
private static WeatherDB weatherDB;
private WeatherDB(Context context) {
DatabaseHelper dataBaseHelper = new DatabaseHelper(context,
DataBaseName, null, VERSION);
database = dataBaseHelper.getWritableDatabase();
}
//获取实例
public static WeatherDB getInstance(Context context) {
if (weatherDB == null) {
weatherDB = new WeatherDB(context);
}
return weatherDB;
}
//保存省份信息
public void saveProvinces(List provinceList) {
if (provinceList != null && provinceList.size() > 0) {
ContentValues values = new ContentValues();
for (int i = 0; i < provinceList.size(); i++) {
values.put("provinceName", provinceList.get(i).getProvinceName());
values.put("provinceId", provinceList.get(i).getProvinceId());
database.insert("Province", null, values);
values.clear();
}
}
}
//保存城市信息
public void saveCities(List cityList) {
if (cityList != null && cityList.size() > 0) {
ContentValues values = new ContentValues();
for (int i = 0; i < cityList.size(); i++) {
values.put("cityName", cityList.get(i).getCityName());
values.put("cityId", cityList.get(i).getCityId());
values.put("provinceId", cityList.get(i).getProvinceId());
database.insert("City", null, values);
values.clear();
}
}
}
//保存乡村信息
public void saveCounties(List countyList) {
if (countyList != null && countyList.size() > 0) {
ContentValues values = new ContentValues();
for (int i = 0; i < countyList.size(); i++) {
values.put("countyName&