标签:type ble 查询 json title 未来 primary line upd
之前写了一款基于Android的空空天气预报,能够查看全国各个省、市、县的未来三天的天气预报,有穿衣指数和运动指数建议;
最近准备找工作了,现在重新回顾一下思路。
主要用到的知识有解析xml技术,解析json,mvc架构。
1、首先看下界面结果;



2、代码思路
2-1 代码架构图

2-2 设计思路
2-2-1 首先解析一个省市县xml文件,里面的代码样式如图:
<province id="01" name="北京"> <city id="0101" name="北京"> <county id="010101" name="北京" weatherCode="101010100"/> <county id="010102" name="海淀" weatherCode="101010200"/> <county id="010103" name="朝阳" weatherCode="101010300"/> <county id="010104" name="顺义" weatherCode="101010400"/> <county id="010105" name="怀柔" weatherCode="101010500"/> <county id="010106" name="通州" weatherCode="101010600"/> <county id="010107" name="昌平" weatherCode="101010700"/> <county id="010108" name="延庆" weatherCode="101010800"/> <county id="010109" name="丰台" weatherCode="101010900"/> <county id="010110" name="石景山" weatherCode="101011000"/> <county id="010111" name="大兴" weatherCode="101011100"/> <county id="010112" name="房山" weatherCode="101011200"/> <county id="010113" name="密云" weatherCode="101011300"/> <county id="010114" name="门头沟" weatherCode="101011400"/> <county id="010115" name="平谷" weatherCode="101011500"/> </city> </province>
2-2-2 模型层的建立
主要是在model层里面建立City、County、Province三个类,下面贴一部分代码:
public class County { private int id;//县城主id private String countyName;//县城名 private String countyCode;//县城代码 private int cityId;//城市id ... public class City { private int id;//城市id private String cityName;//城市名称 private String cityCode;//城市代码 private int provinceId;//省id ... public class Province { private int id;//省id private String provinceName;//省名 private String provinceCode;//省代码 public int getId() { ...
2-2-3 数据库的设计
设计两个类,一个类是CoolWeatherOpenHelper 继承自 SQLiteOpenHelper,用于数据库的创建和更新,大致代码如下:
public class CoolWeatherOpenHelper extends SQLiteOpenHelper { public CoolWeatherOpenHelper(Context context, String name,CursorFactory factory, int version) { super(context, name, factory, version); } //创建省、市、县的sql语句 public static final String CREATE_PROVINCE = "create table Province (" + "id integer primary key autoincrement," + "provinceName text," + "provinceCode text)"; public static final String CREATE_CITY = "create table City (" + "id integer primary key autoincrement," + "cityName text," + "cityCode text," + "provinceId integer)"; public static final String CREATE_COUNTY = "create table County (" + "id integer primary key autoincrement," + "countyName text," + "countyCode text," + "cityId integer)"; //创建数据库 @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_PROVINCE); //create tables db.execSQL(CREATE_CITY); db.execSQL(CREATE_COUNTY); } ...
设计第二个类CoolWeatherDB,用于插入xml文件中省市县的天气预报代码
public class CoolWeatherDB {
/**
* database name 数据库名
*/
public static final String DB_NAME = "cool_weather.db";
/**
* database version ,database is used for operating the database (insert , update, delete, select)
*/
public static final int VERSION = 1;
private static CoolWeatherDB coolWeatherDB;
private SQLiteDatabase db;
/**
* constructor构造函数
*/
private CoolWeatherDB(Context context) {
CoolWeatherOpenHelper dbHelper = new CoolWeatherOpenHelper(context, DB_NAME, null, VERSION);
db = dbHelper.getWritableDatabase();//call onCreate method
}
/**
* get the instance of CoolWeatherDB, use the singleInstance modern
* 获得CoolWeatherDB对象,这里使用了单例模式
*/
public synchronized static CoolWeatherDB getInstance(Context context) {
if(coolWeatherDB == null)
coolWeatherDB = new CoolWeatherDB(context);
return coolWeatherDB;
}
/**
* insert province information to the database
* 插入省信息到数据库中
*/
public void saveProvince(Province province) {
if(province != null) {
ContentValues values = new ContentValues();
values.put("provinceName", province.getProvinceName());
values.put("provinceCode", province.getProvinceCode());
db.insert("Province", null, values);
}
}
/**
* insert a list of provinces
* 插入一系列省信息到数据库中
* @param provinces
*/
public void saveMangProvinces(ArrayList<Province> provinces) {
if(provinces.size() > 0) {
for(Province province: provinces) {
ContentValues values = new ContentValues();
values.put("provinceName", province.getProvinceName());
values.put("provinceCode", province.getProvinceCode());
db.insert("Province", null, values);
}
}
}
/**
* save city
* 插入城市信息到数据库中
*/
public void saveCity(City city) {
if(city != null) {
ContentValues values = new ContentValues();
values.put("cityName", city.getCityName());
values.put("cityCode", city.getCityCode());
values.put("provinceId", city.getProvinceId());
db.insert("City", null, values);
}
}
/**
* insert a list of cities
* 插入一系列的城市信息到数据库中
* @param cities
*/
public void saveMangCities(ArrayList<City> cities) {
if(cities.size() > 0) {
for(City city: cities) {
ContentValues values = new ContentValues();
values.put("cityName", city.getCityName());
values.put("cityCode", city.getCityCode());
values.put("provinceId", city.getProvinceId());
db.insert("City", null, values);
}
}
}
/**
* save county
* 插入县信息到数据库中
*/
public void saveCounty(County county) {
if(county != null) {
ContentValues values = new ContentValues();
values.put("countyName", county.getCountyName());
values.put("countyCode", county.getCountyCode());
values.put("cityId", county.getCityId());
db.insert("County", null, values);
}
}
/**
* 插入一系列县信息到数据库中
* @param counties
*/
public void saveMangCounties(ArrayList<County> counties) {
if(counties.size() > 0) {
for(County county: counties) {
ContentValues values = new ContentValues();
values.put("countyName", county.getCountyName());
values.put("countyCode", county.getCountyCode());
values.put("cityId", county.getCityId());
db.insert("County", null, values);
}
}
}
/**
* get province infor from the db
* 从数据库中获取省信息
*/
public List<Province> loadProvinces() {
List<Province> list = new ArrayList<Province>();
Cursor cursor = db.query("Province", null, null, null, null, null, null);
if(cursor.moveToFirst()) {
do{
Province province = new Province();
province.setId(cursor.getInt(cursor.getColumnIndex("id")));
province.setProvinceName(cursor.getString(cursor.getColumnIndex("provinceName")));
province.setProvinceCode(cursor.getString(cursor.getColumnIndex("provinceCode")));
list.add(province);
}while(cursor.moveToNext());
}
return list;
}
/**
* get city infor from the db by provinceId
* 根据省id从数据库中获取城市信息
*/
public List<City> loadCities(int provinceId) {
List<City> list = new ArrayList<City>();
Cursor cursor = db.query("City", null, "provinceId=?", new String[] {String.valueOf(provinceId)}, null, null, null);
if(cursor.moveToFirst()) {
do{
City city= new City();
city.setId(cursor.getInt(cursor.getColumnIndex("id")));
city.setCityName(cursor.getString(cursor.getColumnIndex("cityName")));
city.setCityCode(cursor.getString(cursor.getColumnIndex("cityCode")));
list.add(city);
}while(cursor.moveToNext());
}
return list;
}
/**
* get county information from the database by cityId
* 根据城市id从数据库中获取县城信息
*/
public List<County> loadCounties(String cityCode) {
List<County> list = new ArrayList<County>();
Cursor cursor = db.query("County", null, "cityId=?", new String[]{String.valueOf(cityCode)}, null, null, null);
if(cursor.moveToFirst()) {
do{
County county = new County();
county.setId(cursor.getInt(cursor.getColumnIndex("id")));
county.setCountyName(cursor.getString(cursor.getColumnIndex("countyName")));
county.setCountyCode(cursor.getString(cursor.getColumnIndex("countyCode")));
county.setCityId(Integer.parseInt(cityCode));
list.add(county);
}while(cursor.moveToNext());
}
return list;
}
}
2-2-4 设计解析xml工具类ParseCity
//用于解析xml中的省市县及对应的代码
public class ParseCity extends Thread {
public static void parse(final InputStream in,final CoolWeatherDB coolWeatherDB) {
new Thread(new Runnable() {
ArrayList<Province> provinces = new ArrayList<Province>();// ArrayList存储多个省
ArrayList<City> cities = new ArrayList<City>();// ArrayList存储多个市
ArrayList<County> counties = new ArrayList<County>();// ArrayList存储多个县
@Override
public void run() {
try {
// 用XmlPullParserFactory去解析xml文件,获取实例
XmlPullParserFactory factory = XmlPullParserFactory
.newInstance();
// 获取XmlPullParser类型的实例
XmlPullParser xmlPullParser = factory.newPullParser();
// 设置输入流和编码类型
xmlPullParser.setInput(in, "utf-8");// set stream
// 获取事件的类型
int eventType = xmlPullParser.getEventType();
// 获得的是事件类型,常用的有:XmlPullParser.END_DOCUMENT(xml文档结束)
// XmlPullParser.START_DOCUMENT(文档开始),XmlPullParser.START_TAG(开始标签)
// XmlPullParser.END_TAG(结束标签).XmlPullParser.TEXT(内容)
String cityid = "";// 城市的id
String fid = "";//设置外键的值
// 使用while循环,解析完整个xml文件
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
// begin to parse somenode 开始解析某个结点
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG: {
//获取xml中的标记名称,有Province、City、County这三种
String tagName = xmlPullParser.getName();
//如果是省的话
if ("province".equals(tagName)) {
// get the count of province
int count = xmlPullParser.getAttributeCount();
String provinceId = null;//省id
String provinceName = null;//省名称
for (int i = 0; i < count; i++) {
// 获取id
String attrName = xmlPullParser.getAttributeName(i);
// 获取省名称 北京
String attrValue = xmlPullParser.getAttributeValue(i);
if ("id".equals(attrName)) {
// 用于设置在城市中的外键
fid = attrValue;
provinceId = attrValue;
} else if ("name".equals(attrName)) {
provinceName = attrValue;
}
}
Province province = new Province();
province.setProvinceCode(provinceId);
province.setProvinceName(provinceName);
// put the parsed data into the list provinces
//保存省信息到数据库中
coolWeatherDB.saveProvince(province);
}
//如果是城市
if ("city".equals(tagName)) {
//获取城市的数量
int count = xmlPullParser.getAttributeCount();
//城市名称
String cityName = null;
//城市代码
String cityCode = null;
//城市的外键,省id
int provinceId = Integer.parseInt(fid);
for (int i = 0; i < count; i++) {
String attrName = xmlPullParser.getAttributeName(i);
String attrValue = xmlPullParser
.getAttributeValue(i);
if ("id".equals(attrName)) {
cityid = attrValue;// set foreign id in
cityCode = attrValue;//城市代码
} else if ("name".equals(attrName)) {
cityName = attrValue;//城市名称
}
}
City city = new City();
city.setCityCode(cityCode);
city.setCityName(cityName);
city.setProvinceId(provinceId);
//在数据库中保存城市
coolWeatherDB.saveCity(city);
// cities.add(city);
}
if ("county".equals(nodeName)) {
int count = xmlPullParser.getAttributeCount();
String countyName = null;//县名称
String countyCode = null;//县代号
int cityId = Integer.parseInt(cityid);//获得城市id
for (int i = 0; i < count; i++) {
String attrName = xmlPullParser.getAttributeName(i);
String attrValue = xmlPullParser.getAttributeValue(i);
if ("id".equals(attrName)) {
} else if ("name".equals(attrName)) {
countyName = attrValue;
} else if ("weatherCode".equals(attrName)) {
countyCode = attrValue;
}
}
County county = new County();
county.setCountyCode(countyCode);
county.setCountyName(countyName);
county.setCityId(cityId);
//保存县值
coolWeatherDB.saveCounty(county);
// counties.add(county);
}
break;
}
case XmlPullParser.END_TAG:
break;
case XmlPullParser.END_DOCUMENT:
/*
* coolWeatherDB.saveMangProvinces(provinces);
* coolWeatherDB.saveMangCities(cities);
* coolWeatherDB.saveMangCounties(counties);
*/
break;
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
2-2-5 选择城市界面
2-2-5-1 首先判断数据库中的内容是否为空,如果为空,那么就去调用ParseCity.parse(open,coolWeatherDB)的方法,如下
try {
//如果数据库为空,那么从xml文件中获得城市代号数据
if(coolWeatherDB.loadProvinces().isEmpty()) {//get infor from xml
showProgressDialog();//显示正在加载
InputStream open = this.getResources().getAssets().open("city.xml");
//调用parseCity
ParseCity.parse(open,coolWeatherDB);
}
} catch (IOException e) {
e.printStackTrace();
}
2-2-5-2 获取数据后,默认显示省级别的城市,当点击其中一个城市后,在改ListView里面的点击事件去处理对应的逻辑,比如点击四川省,就去查询四川省下的城市,点击成都,就去查询成都下面的城市。
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index,long arg3) {
if(currentLevel == LEVEL_RPOVINCE) {
selectedProvince = provinceList.get(index);
queryCities();
}else if(currentLevel == LEVEL_CITY) {
selectedCity = cityList.get(index);
queryCounties();
}else if(currentLevel == LEVEL_COUNTY) {
String countyCode = countyList.get(index).getCountyCode();
//跳转到天气查询界面
Intent intent = new Intent(ChooseAreaActivity.this,WeatherActivity.class);
intent.putExtra("county_code", countyCode);
startActivity(intent);
finish();
}
}
});
下面举一个查询的例子,比如查询省下面的城市,调用queryCities()方法:
private void queryCities() {
cityList = coolWeatherDB.loadCities(selectedProvince.getId());//根据省id查询城市列表
if(cityList.size() > 0){
dataList.clear();
for(City city:cityList) {
dataList.add(city.getCityName());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText(selectedProvince.getProvinceName());
currentLevel = LEVEL_CITY;
}
}
2-2-5-3 如果查询到了最后一个级别,那么跳转到WeatherActivity界面,传递城市代号过去。
String countyCode = countyList.get(index).getCountyCode();
//跳转到天气查询界面
Intent intent = new Intent(ChooseAreaActivity.this,WeatherActivity.class);
intent.putExtra("county_code", countyCode);
startActivity(intent);
finish();
2-2-5-4 WeatherActivity界面代码解析
//获取从ChooseAreaActitivty界面传过来的参数值
String countyCode = getIntent().getStringExtra("county_code");
if(!TextUtils.isEmpty(countyCode)) {
data_y.setText("同步中...");
weatherInfoLayout.setVisibility(View.INVISIBLE);
cityNameText.setVisibility(View.INVISIBLE);
//查询天气信息
queryWeatherCode(countyCode);
//queryWeatherInfor(countyCode);
//new ConnectNetThread(WeatherActivity.this, countyCode).start();
}
private void queryWeatherCode(String countyCode) {
//查询天气预报网址
String address = "http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=" + countyCode;
//查询
queryFromServer(address,"weatherCode");
}
private void queryFromServer(final String address,final String type) {
HttpUtil.sendHttpRequest(address,
new HttpCallbackListener() {
@Override
public void onFinish(String response) {
if("weatherCode".equals(type)) {
//回调处理response字符串,即处理天气预报返回的结果
Utility.hadnleWeatherResponse(WeatherActivity.this, response);
runOnUiThread(new Runnable() {
@Override
public void run() {
//显示天气预报信息
showWeather();
}
});
}
}
@Override
public void onError(Exception e) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
@Override
public void run() {
data_y.setText("同步失败");
}
});
}
});
}
2-2-5-5 然后去HttpUtil.sendHttpRequest()方法中通过连接网络从服务器端获取json数据,回调HttpCallbackListener接口
其中HttpCallbackListener是一个接口
public interface HttpCallbackListener {
void onFinish(String response);//调用完成时的方法
void onError(Exception e);//出现异常时调用的
}
HttpUtil.sendHttpRequest()的具体实现为:
public static void sendHttpRequest(final String address,final HttpCallbackListener listener) {
//create a new thread to execute the method
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try{
URL url = new URL(address);//初始化url对象
//通过url得到HttpURLConnection对象
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
//获取输入字节流
InputStream in = connection.getInputStream();//get inputStream
//将输入字节流转换为带缓冲的输入字符流
BufferedReader reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
StringBuilder response = new StringBuilder();
String line;
while((line=reader.readLine()) != null) {
response.append(line);
}//return response
in.close();
if(listener != null) {
// call back HttpCallbackListener interface: onFinish() method
listener.onFinish(response.toString());
}
}catch(Exception e) {
if(listener != null) {
//call back HttpCallbackListener interface: onError() method
listener.onError(e);
}
}finally{
if(connection != null) {
connection.disconnect();
}
}
}
}).start();
}
HttpUtil.sendHttpRequest()方法执行完后,调用
listener.onFinish(response.toString());
然后返回到WeatherActivity中的queryFromServer方法中
HttpUtil.sendHttpRequest(address,
new HttpCallbackListener() {
@Override
public void onFinish(String response) {
if("weatherCode".equals(type)) {
//回调处理response字符串,即处理天气预报返回的结果
Utility.hadnleWeatherResponse(WeatherActivity.this, response);
runOnUiThread(new Runnable() {
@Override
public void run() {
//显示天气预报信息
showWeather();
}
});
}
}
接着执行Utility.hadnleWeatherResponse()的方法
public static void hadnleWeatherResponse(Context context,String response) {
try {
//新建JSONObject对象
JSONObject jsonObject = new JSONObject(response);
//获取天气预报json对象
JSONObject weatherInfor = jsonObject.getJSONObject("forecast");
//获取json数组
JSONArray jsonArr = jsonObject.getJSONArray("index");
//int iSize = jsonArr.length();
//获取运动指数
JSONObject jsonSports = jsonArr.getJSONObject(1);
//获取穿衣指数
JSONObject jsonWear = jsonArr.getJSONObject(2);
String cityName = weatherInfor.getString("city");
String cityid = weatherInfor.getString("cityid");//not show
String date_y = weatherInfor.getString("date_y");
String wind1 = weatherInfor.getString("wind1");
String weather_desp1 = "今日 " + weatherInfor.getString("temp1") + " " + weatherInfor.getString("weather1");
String weather_desp2 = "明日 " + weatherInfor.getString("temp2") + " " + weatherInfor.getString("weather2");
String weather_desp3 = "后日 " + weatherInfor.getString("temp3") + " " + weatherInfor.getString("weather3");
String sports = jsonSports.getString("name") + "(" + jsonSports.getString("index") + ")\n" + jsonSports.getString("details");
String wear = jsonWear.getString("name") + "(" + jsonWear.getString("index") + ")\n" + jsonWear.getString("details");
//保存天气信息到SharedPreferences的文件中
saveWeatherInfor(context, cityName, cityid, date_y, wind1, weather_desp1, weather_desp2, weather_desp3,sports,wear);
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* save data infor into SharedPreferences file
* 保存数据信息到SharedPreferences里面,在WeatherActivity的showWeather()方法中好调用
*/
public static void saveWeatherInfor(Context context,String cityName,String cityid,String date_y,String wind1,String weather_desp1,String weather_desp2,String weather_desp3,String sports,String wear){
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日",Locale.CHINA);
editor.putBoolean("city_selected", true);
editor.putString("city_name", cityName);
editor.putString("cityid", cityid);
editor.putString("date_y", sdf.format(new Date()));
//String time = sdf.format(new Date());
editor.putString("wind1", wind1);
editor.putString("weather_desp1", weather_desp1);
editor.putString("weather_desp2", weather_desp2);
editor.putString("weather_desp3", weather_desp3);
editor.putString("sports", sports);
editor.putString("wear", wear);
editor.commit();
}
执行完后,再返回到queryFromServer方法中run()的showWeather()方法,显示天气信息
private void showWeather() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
cityNameText.setText(prefs.getString("city_name", ""));
data_y.setText(prefs.getString("date_y", ""));
wind1.setText(prefs.getString("wind1", ""));
weather_desp1.setText(prefs.getString("weather_desp1", ""));
weather_desp2.setText(prefs.getString("weather_desp2", ""));
weather_desp3.setText(prefs.getString("weather_desp3", ""));
sports.setText(prefs.getString("sports", ""));
wear.setText(prefs.getString("wear", ""));
weatherInfoLayout.setVisibility(View.VISIBLE);
cityNameText.setVisibility(View.VISIBLE);
}
这样就成功的查询到了一个城市的天气信息了。
3 整体调用关系图

最后附上代码下载地址
http://files.cnblogs.com/files/fankongkong/CoolWeather.rar
标签:type ble 查询 json title 未来 primary line upd
原文地址:http://www.cnblogs.com/fankongkong/p/6380794.html