简单的天气预报 (三)

本节要完成3个mission。

主要是完成3个工具类,一个是与服务器交互的HttpUtil,另外一个是解析数据的Utility,还有一个是保存天气信息。

mission1:通过联网来获取数据

我们是通过联网来获取省县市的数据的,这就是说我们的程序存在与服务器的交互,那么我们通过一个工具类去与服务器去交互,省去了我们每次都写重复的关于HttpUrlConnection的代码。


我们去创建一个类,叫HttpUtil。

package org.guya.myweather.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUtil {
	public static void sendRequest(final String address,final HttpCallbackListener listener) {
		new Thread(new Runnable() {

			@Override
			public void run() {
				HttpURLConnection conn = null;
				try {
					URL url = new URL(address);
					conn = (HttpURLConnection) url.openConnection();
					conn.setRequestMethod("GET");
					conn.setReadTimeout(5000);
					conn.setConnectTimeout(5000);
					int code = conn.getResponseCode();
					if (code == 200) {
						InputStream is = conn.getInputStream();
						BufferedReader br = new BufferedReader(
								new InputStreamReader(is));
						StringBuilder resp = new StringBuilder();
						String line = null;
						while ((line = br.readLine()) != null) {
							resp.append(line);
						}
						if (resp != null) {
							listener.onFinish(resp.toString());
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
					listener.onError(e);
				} finally {
					conn.disconnect();
				}

			}
		}).start();
	}

}

大致的解释一下上面的代码:联网属于耗时操作,因此要开启子线程去实现联网操作。当响应码为200的时候,说明我们联网成功了,然后我们把数据转化成流的形式,然后去读取数据。返回的数据需要在其他类中使用,但是子线程的数据又不能返回,那么,使用回调的方式去解决。

那么什么时候使用回调呢?举例:某天,我打电话向你请教问题,当然是个难题,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。

接下来去暴露接口:

package org.guya.myweather.utils;

public interface HttpCallbackListener {
	void onFinish(String response);

	void onError(Exception e);

}

然后谁去调用了HttpUtil.sendRequest(final String address,final HttpCallbackListener listener),就去具体实现其中的onFinish()方法,这样就可以获得数据并且处理数据了。如果联网失败,则调用onError()方法。


mission2:解析数据。

    如何获取全国所有省份的信息呢,我们只要要访问以下网址 http://www.weather.com.cn/data/list3/city.xml,就会返回中国所有省份的名称和代号,如下所示。01|北京,02|上海,03|天津,19|江苏等等,我们可以看到城市与其代号之间通过|号相隔开,省份与省份之间用,号隔开,记住这个结构。之后的之后会用到正则表达式去截取。
    如何查看江苏省下的城市的信息呢,其实也非常简单,只需要访问以下网址http://www.weather.com.cn/data/list3/city19.xml,也就是只需要将省级代号添加至city后面就可以了,服务器就会返回数据1901|南京,1902|无锡,1903|镇江,1904|苏州,1905|南通,1906|扬州,1907|盐城,1908|徐州,1909|淮安,1910|连云港,1911|常州,1912|泰州,1913|宿迁。
    同样的方法,我们如果想访问扬州以下的县市的信息,只需要city添加1906即可,如下示         http://www.weather.com.cn/data/list3/city1906.xml,服务器就会返回数据190601|扬州,190602|宝应,190603|仪征,190604|高邮,190605|江都,190606|邗江。
   以上我们就可以知道如何获得全国省市区的信息了,那么如何得到某具体城市的天气呢?以扬州市邗江区为例,县级代号为 190606,那么访问以下网址http://www.weather.com.cn/data/list3/city 190606.xml就会返回一个很简单的数据190606|101190606,后面的就是扬州市邗江区所对应的天气代号,之后我们在用我们这个得到的代号就可以访问以下网址http://www.weather.com.cn/data/cityinfo/ 101190606.html,这样服务器就会把扬州市邗江区的天气信息已json格式的数据返回给我们,如下所示。
{"weatherinfo":{"city":"邗江","cityid":"101190606","temp1":"8℃","temp2":"2℃","weather":"阴转多云","img1":"d2.gif","img2":"n1.gif","ptime":"11:00"}}

经过上面的分析,服务器返回的省市县数据的格式是"代号|城市","代号|城市"这样子的格式。
那么我们就要去用正则表达式分解这样子的数据,来获取省市县。各个 省份与各个省份之间用,号隔开,每个省份和省份代号由|号隔开,城市以及县的数据以此类推。

以省举例子
	/**
	 * 解析和处理服务器返回的省级数据
	 * 
	 * @param weatherDB
	 * @param resp
	 * @return
	 */
	public static boolean handleProvincesResponse(WeatherDB weatherDB,
			String resp) {
		if (!TextUtils.isEmpty(resp)) {
			String[] provinces = resp.split(",");
			if (provinces != null && provinces.length > 0) {
				for (String p : provinces) {
					String[] array = p.split("\\|");
					Province province = new Province();
					province.setProvinceCode(array[0]);
					province.setProvinceName(array[1]);
					weatherDB.saveProvince(province);
				}
			}
			return true;
		}
		return false;

	}

解析天气用的是json解析。
	/**
	 * 解析服务器返回的json数据,并且将数据存储到本地
	 * 
	 * @param context
	 * @param response
	 */
	public static void handleWeatherResponse(Context context, String resp) {
		try {
			JSONObject jsonObject = new JSONObject(resp);
			JSONObject weatherinfo = jsonObject.getJSONObject("weatherinfo");
			String cityName = weatherinfo.getString("city");
			String weatherCode = weatherinfo.getString("cityid");
			String temp1 = weatherinfo.getString("temp1");
			String temp2 = weatherinfo.getString("temp2");
			String weatherDesp = weatherinfo.getString("weather");
			String publishTime = weatherinfo.getString("ptime");
			saveWeatherInfo(context, cityName, weatherCode, temp1, temp2,
					weatherDesp, publishTime);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

mission3:保存天气。
在mission2中的json解析天气方法里,我们调用了一个saveWeatherinfo()方法,该方法调用了SharedPreferences去保存数据。
	private static void saveWeatherInfo(Context context, String cityName,
			String weatherCode, String temp1, String temp2, String weatherDesp,
			String publishTime) {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日", Locale.CHINA);
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(context);
		Editor editor = sp.edit();
		editor.putBoolean("city_selected", true);
		editor.putString("city_name", cityName);
		editor.putString("weather_code", weatherCode);
		editor.putString("temp1", temp1);
		editor.putString("temp2", temp2);
		editor.putString("weather_desp", weatherDesp);
		editor.putString("publish_time", publishTime);
		editor.putString("current_date", sdf.format(new Date()));
		editor.commit();
	}

这样,我们就可以共享天气数据了。

下面给出全部代码
package org.guya.myweather.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.guya.myweather.db.WeatherDB;
import org.guya.myweather.model.City;
import org.guya.myweather.model.County;
import org.guya.myweather.model.Province;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.text.TextUtils;

public class Utility {
	/**
	 * 解析和处理服务器返回的省级数据
	 * 
	 * @param weatherDB
	 * @param resp
	 * @return
	 */
	public static boolean handleProvincesResponse(WeatherDB weatherDB,
			String resp) {
		if (!TextUtils.isEmpty(resp)) {
			String[] provinces = resp.split(",");
			if (provinces != null && provinces.length > 0) {
				for (String p : provinces) {
					String[] array = p.split("\\|");
					Province province = new Province();
					province.setProvinceCode(array[0]);
					province.setProvinceName(array[1]);
					weatherDB.saveProvince(province);
				}
			}
			return true;
		}
		return false;

	}

	/**
	 * 解析和处理服务器返回的城市数据
	 * 
	 * @param WeatherDB
	 * @param response
	 * @param provinceId
	 * @return
	 */
	public synchronized static boolean handleCitiesResponse(
			WeatherDB WeatherDB, String resp, int provinceId) {
		if (!TextUtils.isEmpty(resp)) {
			String[] allCities = resp.split(",");
			if (allCities.length > 0 && allCities != null) {
				for (String c : allCities) {
					String[] array = c.split("\\|");
					City city = new City();
					city.setCityCode(array[0]);
					city.setCityName(array[1]);
					city.setProvinceId(provinceId);
					WeatherDB.saveCity(city);
				}

				return true;
			}
		}

		return false;
	}

	/**
	 * 解析和处理服务器返回的县级数据
	 * 
	 * @param WeatherDB
	 * @param resp
	 * @param cityId
	 * @return
	 */
	public synchronized static boolean handleCountiesResponse(
			WeatherDB WeatherDB, String resp, int cityId) {
		if (!TextUtils.isEmpty(resp)) {
			String[] allCounties = resp.split(",");
			if (allCounties.length > 0 && allCounties != null) {
				for (String c : allCounties) {
					String[] array = c.split("\\|");
					County county = new County();
					county.setCountyCode(array[0]);
					county.setCountyName(array[1]);
					county.setCityId(cityId);
					WeatherDB.saveCounty(county);
				}

				return true;
			}
		}

		return false;
	}

	/**
	 * 解析服务器返回的json数据,并且将数据存储到本地
	 * 
	 * @param context
	 * @param response
	 */
	public static void handleWeatherResponse(Context context, String resp) {
		try {
			JSONObject jsonObject = new JSONObject(resp);
			JSONObject weatherinfo = jsonObject.getJSONObject("weatherinfo");
			String cityName = weatherinfo.getString("city");
			String weatherCode = weatherinfo.getString("cityid");
			String temp1 = weatherinfo.getString("temp1");
			String temp2 = weatherinfo.getString("temp2");
			String weatherDesp = weatherinfo.getString("weather");
			String publishTime = weatherinfo.getString("ptime");
			saveWeatherInfo(context, cityName, weatherCode, temp1, temp2,
					weatherDesp, publishTime);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void saveWeatherInfo(Context context, String cityName,
			String weatherCode, String temp1, String temp2, String weatherDesp,
			String publishTime) {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日", Locale.CHINA);
		SharedPreferences sp = PreferenceManager
				.getDefaultSharedPreferences(context);
		Editor editor = sp.edit();
		editor.putBoolean("city_selected", true);
		editor.putString("city_name", cityName);
		editor.putString("weather_code", weatherCode);
		editor.putString("temp1", temp1);
		editor.putString("temp2", temp2);
		editor.putString("weather_desp", weatherDesp);
		editor.putString("publish_time", publishTime);
		editor.putString("current_date", sdf.format(new Date()));
		editor.commit();
	}

}

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值