文章目录

查询天气的接口

目前阶段我们是本地练习,没有后台数据提供,我们可以利用 ​​聚合数据​​ 提供的免费 api 找到自己想要的数据。聚合数据也提供免费的 api 来查询天气。

这里介绍另一个请求天气状况的接口:

http://wthrcdn.etouch.cn/WeatherApi?city=北京

后面 city 这个参数传入想查询的城市即可。

请求回来数据结构如下
【达内课程】xml练习:查询天气预报_xml
可以看到返回的信息有:城市姓名、更新时间、温度、风力等信息,其中 yesterday 标签内是昨天的天气,forecast 标签内是未来天气的信息。

我们关注下 forecast 标签里的内容,结构如下:
【达内课程】xml练习:查询天气预报_天气预报_02

代码实现

我们基于上一节的​​省份联动​​实现,点击相应城市查询城市天气,所以我们在上一节增加和修改以下代码:

1、增加一个用于描述响应的模型 Resp

public class Resp {
private String city;//北京
private String updatetime;//08:32
private String wendu;//26
private String shidu;//43%
private String fengxiang;//北风
private String sunrise_1;//05:38
private String sunset_1;//18:51
private List<Weather> forecast;

public Resp() {
}

public List<Weather> getForecast() {
return forecast;
}

public void setForecast(List<Weather> forecast) {
this.forecast = forecast;
}

public Resp(String city, String updatetime, String wendu, String shidu, String fengxiang, String sunrise_1, String sunset_1, List<Weather> forecast) {

this.city = city;
this.updatetime = updatetime;
this.wendu = wendu;
this.shidu = shidu;
this.fengxiang = fengxiang;
this.sunrise_1 = sunrise_1;
this.sunset_1 = sunset_1;
this.forecast = forecast;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getUpdatetime() {
return updatetime;
}

public void setUpdatetime(String updatetime) {
this.updatetime = updatetime;
}

public String getWendu() {
return wendu;
}

public void setWendu(String wendu) {
this.wendu = wendu;
}

public String getShidu() {
return shidu;
}

public void setShidu(String shidu) {
this.shidu = shidu;
}

public String getFengxiang() {
return fengxiang;
}

public void setFengxiang(String fengxiang) {
this.fengxiang = fengxiang;
}

public String getSunrise_1() {
return sunrise_1;
}

public void setSunrise_1(String sunrise_1) {
this.sunrise_1 = sunrise_1;
}

public String getSunset_1() {
return sunset_1;
}

public void setSunset_1(String sunset_1) {
this.sunset_1 = sunset_1;
}
}

Weather

public class Weather {
private String date;/29日星期三
private String high;//高温 31℃
private String low;//低温 20℃

public Weather() {
}

public Weather(String date, String high, String low) {
this.date = date;
this.high = high;
this.low = low;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

public String getHigh() {
return high;
}

public void setHigh(String high) {
this.high = high;
}

public String getLow() {
return low;
}

public void setLow(String low) {
this.low = low;
}
}

我们在上一节的 xml 中增加 3 个 TextView 来显示日期、最高温、最低温

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ListView
android:id="@+id/lvProvince"
android:layout_width="0dp"
android:layout_height="300dp"
android:layout_weight="1" />

<ListView
android:id="@+id/lvCity"
android:layout_width="0dp"
android:layout_height="300dp"
android:layout_weight="1" />
</LinearLayout>

<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="日期"
android:textSize="18sp" />

<TextView
android:id="@+id/tv_high"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="最高温"
android:textSize="18sp" />

<TextView
android:id="@+id/tv_low"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:text="最低温"
android:textSize="18sp" />
</LinearLayout>

TestActivity 修改如下:

增加了 ​​List<Weather> forecast​​​ 来存储我们要显示的日期、最高温、最低温
​​​setViews()​​​ 中增加了新增的 TextView 的控件声明
设置监听的方法​​​setListeners()​​​ 中增加了城市的点击事件,我们之前已经存储了点击省份要展示的城市变量 cities,通过点击的 position 可以得到城市名称,开启一个线程调用​​queryWeather(name)​​方法来查询天气

public class TestActivity extends Activity {
......

private List<Weather> forecast;
private TextView date;
private TextView high;
private TextView low;
public static final int UPDATE_WEATHER = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_WEATHER:
date.setText("日期:" + forecast.get(0).getDate());
high.setText("最高温:" + forecast.get(0).getHigh());
low.setText("最低温:" + forecast.get(0).getLow());
break;
}
}
};

......

private void setViews() {
lvProvince = findViewById(R.id.lvProvince);
lvCity = findViewById(R.id.lvCity);

date = findViewById(R.id.tv_date);
high = findViewById(R.id.tv_high);
low = findViewById(R.id.tv_low);
}

......

/**
* 设置监听
*/
private void setListeners() {
......

//城市列表的监听
lvCity.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
City city = cities.get(i);
final String name = city.getName();
//发送请求,访问该城市天气预报
new Thread() {
@Override
public void run() {
try {
queryWeather(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
});
}


/**
* 发送请求,在工作线程执行
*
* @param name
*/
private void queryWeather(String name) throws Exception {
//get请求中含有中文参数,则把url进行中文转码
name = URLEncoder.encode(name, "utf-8");
URL url = new URL("http://wthrcdn.etouch.cn/WeatherApi?city=" + name);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
//解析XML
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String xml = sb.toString();
Log.d("info", xml);

XmlPullParser parser = Xml.newPullParser();
InputStream xmlInputStream = new ByteArrayInputStream(xml.getBytes());
parser.setInput(xmlInputStream, "utf-8");
int type = parser.getEventType();
forecast = new ArrayList<Weather>();
Weather weather = null;
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
//碰到了开始标记
case XmlPullParser.START_TAG:
String tag = parser.getName();
if (tag.equals("weather")) {
weather = new Weather();
} else if (tag.equals("date")) {
weather.setDate(parser.nextText());
} else if (tag.equals("high")) {
weather.setHigh(parser.nextText());
} else if (tag.equals("low")) {
weather.setLow(parser.nextText());
forecast.add(weather);
}
break;
default:
break;
}
type = parser.next();
}
handler.sendEmptyMessage(UPDATE_WEATHER);
}
}

queryWeather 方法得到通过接口返回的数据,并进行了 xml 解析,然后通过 handler 发送信息,更新页面 TextView 的值。

记得加上网络权限

<uses-permission android:name="android.permission.INTERNET" />

运行程序:
【达内课程】xml练习:查询天气预报_android_03