Android 天气预报【解析XML / Json文件(2种方式:手动解析、Gson库解析)】

源码 [工程文件]:https://gitee.com/lwx001/Weather

在这里插入图片描述

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">

    <TextView
        android:id="@+id/tv_city"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/tv_weather"
        android:layout_alignRight="@+id/tv_weather"
        android:layout_alignParentTop="true"
        android:layout_marginTop="39dp"
        android:text="上海"
        android:textSize="50sp" />

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_below="@+id/tv_city"
        android:layout_alignStart="@+id/ll_btn"
        android:layout_alignLeft="@+id/ll_btn"
        android:layout_marginStart="44dp"
        android:layout_marginLeft="44dp"
        android:layout_marginTop="42dp"
        android:paddingBottom="5dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/tv_weather"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/iv_icon"
        android:layout_alignRight="@+id/iv_icon"
        android:layout_marginTop="18dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:text="多云"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/iv_icon"
        android:layout_marginStart="39dp"
        android:layout_marginLeft="39dp"
        android:layout_toEndOf="@+id/iv_icon"
        android:layout_toRightOf="@+id/iv_icon"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_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/tv_wind"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="风力:3级"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_pm"
            android:layout_width="73dp"
            android:layout_height="wrap_content"
            android:text="pm"
            android:textSize="18sp" />
    </LinearLayout>

    <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/btn_bj"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="北京" />

        <Button
            android:id="@+id/btn_sh"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上海" />

        <Button
            android:id="@+id/btn_gz"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="广州" />
    </LinearLayout>
</RelativeLayout>

weather1.xml【res\raw目录下】 :
raw中的文件会被自动解析、编译。通过raw目录找到相应的文件。

<?xml version="1.0" encoding="utf-8"?>
<infos>
    <city id="sh">
        <temp>20/30</temp>
        <weather>晴天多云</weather>
        <name>上海</name>
        <pm>80</pm>
        <wind>1</wind>
    </city>
    <city id="bj">
        <temp>26/32</temp>
        <weather>晴天</weather>
        <name>北京</name>
        <pm>98</pm>
        <wind>3</wind>
    </city>
    <city id="gz">
        <temp>15/24</temp>
        <weather>多云</weather>
        <name>广州</name>
        <pm>30</pm>
        <wind>5</wind>
    </city>
</infos>

MainActivity.java :

package cn.lwx.weather;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tvCity;
    private TextView tvWeather;
    private TextView tvTemp;
    private TextView tvWind;
    private TextView tvPm;
    private ImageView ivIcon;
    private List<Map<String, String>> list;//存储天气信息的集合
    private Map<String, String> map;
    private String temp, weather, name, pm, wind;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //raw中的文件会被自动解析、编译。通过raw目录找到相应的文件

        //1、初始化文本控件
        initView();

        //2、读取解析weather1.xml文件信息 / getResources()得到资源文件
        InputStream inputStream = getResources().openRawResource(R.raw.weather1);
        try {
        	//调用工具类[传参:inputStream流]
            List<WeatherInfo> weatherInfos = WeatherService.getInfosFromXML(inputStream);
            list = new ArrayList<Map<String, String>>();//存储天气信息的集合
            //循环读取weatherInfos中的每一条数据
            for (WeatherInfo info : weatherInfos) {
                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();
        }

        //自定义getMap()方法,显示天气信息到文本控件中,默认显示北京的天气
        getMap(1, R.drawable.sun);
    }

    private void initView() {
        tvCity = (TextView) findViewById(R.id.tv_city);
        tvWeather = (TextView) findViewById(R.id.tv_weather);
        tvTemp = (TextView) findViewById(R.id.tv_temp);
        tvWind = (TextView) findViewById(R.id.tv_wind);
        tvPm = (TextView) findViewById(R.id.tv_pm);
        ivIcon = (ImageView) findViewById(R.id.iv_icon);//展示图片
        findViewById(R.id.btn_sh).setOnClickListener(this);//设置点击
        findViewById(R.id.btn_bj).setOnClickListener(this);
        findViewById(R.id.btn_gz).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_sh://点击上海
                getMap(0, R.drawable.cloud_sun);
                break;
            case R.id.btn_bj://点击北京
                getMap(1, R.drawable.sun);
                break;
            case R.id.btn_gz://点击广州
                getMap(2, R.drawable.clouds);
                break;
        }
    }

    //自定义getMap()方法,将城市天气信息分条展示到界面上,默认显示北京天气
    private void getMap(int number, int iconNumber) {
        Map<String, String> cityMap = list.get(number);
        temp = cityMap.get("temp");
        weather = cityMap.get("weather");
        name = cityMap.get("name");
        pm = cityMap.get("pm");
        wind = cityMap.get("wind");
        tvCity.setText(name);
        tvWeather.setText(weather);
        tvTemp.setText("" + temp);
        tvWind.setText("风力  : " + wind);
        tvPm.setText("pm: " + pm);
        ivIcon.setImageResource(iconNumber);
    }
}

WeatherInfo.java :

package cn.lwx.weather;

/**
 * 创建天气的实体类
 */
public class WeatherInfo {
    private String id;
    private String temp;
    private String weather;
    private String name;
    private String pm;
    private String wind;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    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.java :

package cn.lwx.weather;

import android.util.Xml;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.json.JSONArray;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 解析天气的工具类
 */
public class WeatherService {

    //解析xml文件返回天气信息的集合 [存储解析信息的集合] 接收InputStream流
    public static List<WeatherInfo> getInfosFromXML(InputStream is) throws Exception {
        //1、获取pull解析器
        XmlPullParser parser = Xml.newPullParser();//工具类
        //2、初始化解析器,第一个参数代表包含xml的数据
        parser.setInput(is, "utf-8");//流、编码

        List<WeatherInfo> weatherInfos = null;
        WeatherInfo weatherInfo = null;

        //3、得到当前事件的类型
        int type = parser.getEventType();
        //4、不到文件的结尾,就一直解析。END_DOCUMENT: 文档结束标签
        while (type != XmlPullParser.END_DOCUMENT) {
            //5、具体判断一下解析的是什么标签(开始标签or结束标签)。
            switch (type) {
                //一个节点的开始标签
                case XmlPullParser.START_TAG://代表 解析 开始标签
                    //解析到全局开始的标签 infos 根节点
                    if ("infos".equals(parser.getName())) {//parser.getName(): 拿到当前标签的名字
                        weatherInfos = new ArrayList<WeatherInfo>();//创建集合对象
                    } else if ("city".equals(parser.getName())) {
                        weatherInfo = new WeatherInfo();//初始化weatherInfo的信息
                        String idStr = parser.getAttributeValue(0);//获取weather1.xml文件中city的id值
                        weatherInfo.setId(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);//把bean对象加到集合中
                        weatherInfo = null;
                    }
                    break;
            }
            type = parser.next();//赋值:解析后的事件类型-下一个事件的类型
        }
        return weatherInfos;
    }



    //json比xml更轻量、更易于阅读
    //解析json文件返回天气信息的集合【使用封装好的jar包】
    public static List<WeatherInfo> getInfosFromJson(InputStream is) throws IOException {
        byte[] buffer = new byte[is.available()];
        is.read(buffer);//把流中的数据读到缓冲区中
        //通过buffer数组构造新字符串。读取json数据
        String json = new String(buffer, "utf-8");
        //使用gson库解析JSON数据
        Gson gson = new Gson();
        //定义类型(定义一个什么样的类型)【TypeToken-->想要的类型】
        Type listType = new TypeToken<List<WeatherInfo>>() {
        }.getType();
        //解析。两个参数(json串、返回类型)
        List<WeatherInfo> weatherInfos = gson.fromJson(json, listType);
        return weatherInfos;
    }



	/**
	* 解析json文件返回天气信息的集合
	* [
	* {"temp":"20℃/30℃","weather":"晴转多云","name":"上海","pm":"80","wind":"1级"},
	* {"temp":"15℃/24℃","weather":"晴","name":"北京","pm":"98","wind":"3级"},
	* {"temp":"26℃/32℃","weather":"多云","name":"广州","pm":"30","wind":"2级"}
	* ]
	*
	* @param is 输入流
	* @return 城市天气列表
	* @throws Exception
	*/
    public static List<WeatherInfo> getInfosFromJson2(InputStream is) throws Exception {
        List<WeatherInfo> weatherInfos = new ArrayList<>();
        WeatherInfo info;
        //字节流-->字符串
        byte[] buffer = new byte[is.available()];
        is.read(buffer);
        String json = new String(buffer, "utf-8");
        /**
         * 1.[]  JSONArray array=new JSONArray(json);
         * 2.{}  JSONObject obj=new JSONObject(json);
         * 3.optJSONArray、optJSONObject
         * optString
         */
        JSONArray array = new JSONArray(json); // []将字符串转为json数组;{}大括号开始---jsonObject
        for (int i = 0; i < array.length(); i++) { // 对数组进行遍历,对所有对象进行处理---循环3次
            JSONObject object = array.optJSONObject(i); // 官方建议【可以处理异常】获取对象
            //JSONObject object=array.getJSONObject(i); // 作用与上一行相同
            info = new WeatherInfo();
            info.setWind(object.optString("wind")); // 根据key,获取具体属性
            info.setTemp(object.optString("temp"));
            info.setName(object.optString("name"));
            info.setPm(object.optString("pm"));
            info.setWeather(object.getString("weather"));
            weatherInfos.add(info);
            //info = null;
        }
        return weatherInfos;
    }

}

JSON :

在这里插入图片描述

添加库文件 ( json ):
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
若添加gson包失败,可更改build.gradle文件,然后重启项目:
在这里插入图片描述
build.gradle :

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    
    repositories {
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
        maven { url "https://jitpack.io" }
        google()
        //jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'}
        maven { url "https://jitpack.io" }
        google()
        //jcenter()

    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

在这里插入图片描述
weather2.json :

[
  {"temp":"20℃/30℃","weather":"晴转多云","name":"上海","pm":"80","wind":"1级"},
  {"temp":"15℃/24℃","weather":"晴","name":"北京","pm":"98","wind":"3级"},
  {"temp":"26℃/32℃","weather":"多云","name":"广州","pm":"30","wind":"2级"}
]

更改 MainActivity.java 文件 :
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

upward337

谢谢老板~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值