Android学习笔记整理(12)--XML解析及天气预报案例

版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。 https://blog.csdn.net/qq_29477223/article/details/80834119

1.XML解析

若想要操作XML文档,首先需要将XML文档解析出来。通常情况下,解析XML文件有三种方式

  • DOM解析

DOM(Document Object Mode)解析是一种基于对象的API,它会将XML文件的所有内容以文档树方式存放在内存中,然后允许使用DOM API遍历XML树、检索所需的数据,这样便能根据树的结构以节点的形式来

DOM操作XML代码看起来是比较直观,编码比SAX解析简单,但DOM需要将整个XML文档以文档树的形式存放在内存,消耗内存比较大。

  • SAX解析

SAX解析会逐行扫描XML文档,当遇到标签时触发解析处理器,采用事件处理方式解析XML。由于它是边读取边解析,因此不存在内存占用的问题,可以解析超大XML。缺点是SAX解析只能读取XML中的数据,无法进行增删改

  • PULL解析

PULL解析器是一个开源的Java项目,既可以用于Android应用,也可以用于JavaEE程序。Android已经集成了PULL解析器,所以在Android中最常用的解析方式是PULL解析。

使用PULL解析XML文档,首先要创建XmlPullParser解析器,该解析器提供了很多属性

        XmlPullParser.START_DOCUMENT:XML文档的开始

        XmlPullParser.END_DUCUMENT:XML文档的结束

        XmlPullParser.START_TAG:开始节点,在XML文件中,带<>的都是开始节点

        XmlPullParser.END_TAG:结束节点,带有</>都是结束节点

PULL解析器的用法:

(1)通过调用Xml.newPullParser();得到一个XmlPullParser对象

(2)通过parser.getEventType()获取到当前的事件类型

(3)通过while循环判断当前操作事件类型是否为文档结束,是则跳出while循环

(4)while循环中通过switch语句判断当前事件类型是否为开始标签,是则获取该标签内容

2.案例--天气预报(解析XML文件)

第一步,编写主布局(activity_main.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/weather"
    tools:context=".MainActivity" >
    <LinearLayout
        android:id="@+id/ll_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:orientation="horizontal" >
        <Button
            android:id="@+id/city_bj"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="北京" />
        <Button
            android:id="@+id/city_sh"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上海" />
        <Button
            android:id="@+id/city_Harbin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="吉林" />
    </LinearLayout>
    <TextView
        android:id="@+id/select_city"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="34dp"
        android:layout_toLeftOf="@+id/icon"
        android:text="上海"
        android:textSize="20sp" />
    <ImageView
        android:id="@+id/icon"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_alignLeft="@+id/ll_btn"
        android:layout_below="@+id/select_city"
        android:layout_marginTop="25dp"
        android:paddingBottom="5dp"
        android:src="@drawable/ic_launcher" />
    <TextView
        android:id="@+id/select_weather"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/icon"
        android:layout_below="@+id/icon"
        android:layout_marginRight="15dp"
        android:layout_marginTop="18dp"
        android:gravity="center"
        android:text="多云"
        android:textSize="18sp" />
    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/select_weather"
        android:layout_alignRight="@+id/ll_btn"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="vertical" >
        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center_vertical"
            android:text="-7℃"
            android:textSize="22sp" />
        <TextView
            android:id="@+id/wind"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="风力:3级"
            android:textSize="18sp" />
        <TextView
            android:id="@+id/pm"
            android:layout_width="73dp"
            android:layout_height="wrap_content"
            android:text="pm"
            android:textSize="18sp" />
    </LinearLayout>
</RelativeLayout>

显示效果如图


第二步,创建weather,xml文件

在src根目录中创建一个weather.xml文件,该文件包含三个城市的天气信息

<?xml version="1.0" encoding="utf-8"?>
<infos>
<city id="1">
		<temp>20℃/30℃</temp>
		<weather>晴天多云</weather>
		<name>上海</name>
		<pm>80</pm>
		<wind>1级</wind>
</city>
<city id="2">
		<temp>26℃/32℃</temp>
		<weather>晴天</weather>
		<name>北京</name>
		<pm>98</pm>
		<wind>3级</wind>
</city>
<city id="3">
		<temp>15℃/24℃</temp>
		<weather>多云</weather>
		<name>哈尔滨</name>
		<pm>30</pm>
		<wind>5级</wind>
</city>
</infos>

第三步,创建WeatherInfo类

每个城市天气信息都包含id,temp,weather,name,pm和wind属性

public class WeatherInfo {
	private int id;
	private String name;
	private String weather;
	private String temp;
	private String pm;
	private String wind;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getWeather() {
		return weather;
	}
	public void setWeather(String weather) {
		this.weather = weather;
	}
	public String getTemp() {
		return temp;
	}
	public void setTemp(String temp) {
		this.temp = temp;
	}
	public String getPm() {
		return pm;
	}
	public void setPm(String pm) {
		this.pm = pm;
	}
	public String getWind() {
		return wind;
	}
	public void setWind(String wind) {
		this.wind = wind;
	}
}

第四步,创建WeatherService工具类

为了避免大量代码都在一个类中,因此创建了一个的工具类,类中定义了一个getWeatherInfo()方法,用来解析XML文件

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
public class WeatherService {
	//返回天气信息的集合
		public static List<WeatherInfo> getWeatherInfos(InputStream is) 
	throws Exception {
			//得到pull解析器
			XmlPullParser parser = Xml.newPullParser();
			// 初始化解析器,第一个参数代表包含xml的数据
			parser.setInput(is, "utf-8");
			List<WeatherInfo> weatherInfos = null;
			WeatherInfo weatherInfo = null;
			//得到当前事件的类型
			int type = parser.getEventType();
			// END_DOCUMENT文档结束标签 
			while (type != XmlPullParser.END_DOCUMENT) {
				switch (type) {
				//一个节点的开始标签
				case XmlPullParser.START_TAG:
					//解析到全局开始的标签 infos 根节点
					if("infos".equals(parser.getName())){
						weatherInfos = new ArrayList<WeatherInfo>();
					}else if("city".equals(parser.getName())){
						weatherInfo = new WeatherInfo();
						String idStr = parser.getAttributeValue(0);
						weatherInfo.setId(Integer.parseInt(idStr));
					}else if("temp".equals(parser.getName())){
					     //parset.nextText()得到该tag节点中的内容
						String temp = parser.nextText();
						weatherInfo.setTemp(temp);
					}else if("weather".equals(parser.getName())){
						String weather = parser.nextText();
						weatherInfo.setWeather(weather);
					}else if("name".equals(parser.getName())){
						String name = parser.nextText();
						weatherInfo.setName(name);
					}else if("pm".equals(parser.getName())){
						String pm = parser.nextText();
						weatherInfo.setPm(pm);
					}else if("wind".equals(parser.getName())){
						String wind = parser.nextText();
						weatherInfo.setWind(wind);
					}
					break;
				//一个节点结束的标签
				case XmlPullParser.END_TAG:
					//一个城市的信息处理完毕,city的结束标签
					if("city".equals(parser.getName())){
						//一个城市的信息 已经处理完毕了.
						weatherInfos.add(weatherInfo);
						weatherInfo = null;
					}
					break;
				}
				//只要不解析到文档末尾,就解析下一个条目。得到下一个节点的事件类型
				//注意,这个一定不能忘,否则会成为死循环
				type = parser.next();
			}
			return weatherInfos;
		}
}

注意的是,type=parser.next()这行代码不能忘记,因为在while循环中,当一个节点信息解析完毕,会继续解析下一个节点,只有type的类型为END_DOCUMENT时才会结束循环。

第五步,编写界面交互代码(MainActivity类)

public class MainActivity extends Activity implements OnClickListener {
	private TextView select_city, select_weather, select_temp, select_wind,select_pm;
	private Map<String, String> map;
	private List<Map<String, String>> list;
	private String temp, weather, name, pm, wind;
	private ImageView icon;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 初始化文本控件
		select_city = (TextView) findViewById(R.id.select_city);
		select_weather = (TextView) findViewById(R.id.select_weather);
		select_temp = (TextView) findViewById(R.id.temp);
		select_wind = (TextView) findViewById(R.id.wind);
		select_pm = (TextView) findViewById(R.id.pm);
		icon = (ImageView) findViewById(R.id.icon);
		findViewById(R.id.city_sh).setOnClickListener(this);
		findViewById(R.id.city_bj).setOnClickListener(this);
		findViewById(R.id.city_Harbin).setOnClickListener(this);
		try {
			// 调用上边写好的解析方法,weather.xml就在类的目录下,使用类加载器进行加载
			// infos就是每个城市的天气信息集合,里边有我们所需要的所有数据。
			List<WeatherInfo> infos = WeatherService
					.getWeatherInfos(MainActivity.class.getClassLoader()
							.getResourceAsStream("weather.xml"));
			// 循环读取infos中的每一条数据
			list = new ArrayList<Map<String, String>>();
			for (WeatherInfo info : infos) {
				map = new HashMap<String, String>();
				map.put("temp", info.getTemp());
				map.put("weather", info.getWeather());
				map.put("name", info.getName());
				map.put("pm", info.getPm());
				map.put("wind", info.getWind());
				list.add(map);
			}
			// 显示天气信息到文本控件中
		} catch (Exception e) {
			e.printStackTrace();
			Toast.makeText(this, "解析信息失败", 0).show();
		}
		getMap(1, R.drawable.sun);
	}
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.city_sh:
			getMap(0, R.drawable.cloud_sun);
			break;
		case R.id.city_bj:
			getMap(1, R.drawable.sun);
			break;
		case R.id.city_Harbin:
			getMap(2, R.drawable.clouds);
			break;
		}
	}
	private void getMap(int number, int iconNumber) {
		Map<String, String> bjMap = list.get(number);
		temp = bjMap.get("temp");
		weather = bjMap.get("weather");
		name = bjMap.get("name");
		pm = bjMap.get("pm");
		wind = bjMap.get("wind");
		select_city.setText(name);
		select_weather.setText(weather);
		select_temp.setText("" + temp);
		select_wind.setText("风力  : " + wind);
		select_pm.setText("pm: " + pm);
		icon.setImageResource(iconNumber);
	}
}

第六步,运行程序查看天气

运行当前程序,分别选择,能看到图中所示结果,代表着程序成功地解析了存储在weather.xml文件中的天气信息





猜你喜欢

转载自blog.csdn.net/qq_29477223/article/details/80834119