在开发天气app的过程中,需要随时从网络获取最新的天气情况,并且获取完天气数据之后要更新UI,但是网络请求是耗时操作,主线程不可能等着网络加载结束之后获取数据,并且因为多个地方都要根据天气情况进行更新,因此这个时候用观察者模式是最合适的了。
获取天气的类就属于被观察者,需要更新天气的地方就是观察者,所以我们首先要定义接口、被观察者类,然后在需要地方添加观察者
import java.util.List;
public interface WeatherDataListener {
void onWeatherDataLoaded(List<WeatherInfo> weatherInfoList);
}
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
public class Weather {
private String cityName;//对外的接口,城市名称
//记录当前界面需要信息,日期、天气,最高温度、最低温度
private List<WeatherInfo> weatherInfoList = new ArrayList<>();//weatherInfoList 是一个存放了日期、天气,最高温度、最低温度的类
private String wea_URL_head="********";//用于根据城市名称拼凑对应天气接口URL,处于保密这里就没有公开,你可以在和风天气上申请一个接口账号
private List<WeatherDataListener> listenerList;//存放所有的观察者,在需要回调的时候轮询就可以
//在观察者new了天气类和重载了接口方法之后,需要将当前观察加入到观察队列中
public void addWeatherDataListener(WeatherDataListener listener) {
if(listenerList == null)
listenerList = new ArrayList<>();
listenerList.add(listener);
}
//请求城市的三天天气,并更新
public void requestWeather(String cityName) {
this.cityName=cityName;
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(weatherUrl());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream in = connection.getInputStream();
BufferedReader buffer = new BufferedReader(new InputStreamReader(in));
StringBuilder builder = new StringBuilder();
String s;
if ((s = buffer.readLine()) != null)
builder.append(s);
parseData(builder.toString());
//weatherDataListener.onWeatherDataLoaded(weatherInfoList);
for(WeatherDataListener w : listenerList) {
w.onWeatherDataLoaded(weatherInfoList);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 将中文名称的城市转换为对应的天气接口
* @param paramString城市名称,例如“深圳”
*/
private String weatherUrl() {
String name =toURLEncoded(cityName);
return (wea_URL_head+name);
}
/**
* 将中文汉字转化为url
*/
private static String toURLEncoded(String paramString) {
if (paramString == null || paramString.equals("")) {
return "";
}
try
{
String str = new String(paramString.getBytes(), "UTF-8");
str = URLEncoder.encode(str, "UTF-8");
return str;
}
catch (Exception localException)
{
localException.printStackTrace();
}
return "";
}
/**
* 将GSON格式的String进行解析,并放入weather中
* @param s
*/
private void parseData(String s) {
try {
JSONObject jsonObject = new JSONObject(s);
JSONArray array = jsonObject.getJSONArray("days");
for (int i = 0; i < 3; i++) {
JSONObject day = array.getJSONObject(i);
WeatherInfo info = new WeatherInfo();
info.date = day.getString("date");
info.weatherCondition = day.getString("Weather");
info.maxDegree = day.getInt("MaxDegree");
info.minDegree = day.getInt("MinDegree");
weatherInfoList.add(info);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
接下来就是在需要更新天气的地方设置观察者了
Weather weather=new Weather();
WeatherDataListener weatherDataListener=new WeatherDataListener() {
@Override
public void onWeatherDataLoaded(List<WeatherInfo> weatherInfoList) {
//获得天气数据之后的操作
Log.d("weatherInfoList",weatherInfoList.get(0).weatherCondition);
}
};
weather.addWeatherDataListener(weatherDataListener);
weather.requestWeather(cityName);
搞定!