Android 天气APP(十九)更换新版API接口(更高、更快、更强)

时间:2022-07-25
本文章向大家介绍Android 天气APP(十九)更换新版API接口(更高、更快、更强),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

近段时间,和风天气上线了新的API版本,并且给所有的和风开发者发送了邮件,好像是7月10号,哪个时候我去看了一下,发现改动还是有的,和风天气V7版开发API文档,并且提到之前的版本也就是和风天气S6版开发API文档这个S6的版本会在2020年12月31日下线且不再提供技术支持,我相信之前看到文章的朋友都是用的S6的API接口,虽然离下线还比较早,但是尝试新鲜的API也是极好的,本来之前就想写关于API改动变化的,但是天不随人愿,工作上增加了任务,无法抽身,文章也是利用碎片时间来写的OK,话不多说了,进入正题吧。

正文

建议先去看一下和风天气V7版开发API文档这个,再开始下面的文章阅读,否则你会产生疑问,因为接口和数据的变化其实是挺大的。先来回顾一下S6版本中的开发者有哪些数据

这是在Android 天气APP(十二)空气质量、UI优化调整提到的,也是在这一篇文章中,从普通用户升级到了开发者,拿到更多的数据。再看V7版本的

这里我们可以对比S6中开发者得出多了一些免费数据可以白嫖。嗯!划重点,又能白嫖了,这算是一个好消息啊,现在你就知道你可以获取什么数据了。对比一下相信你已经之后你可以获得那些数据了。但是获取到的数据怎么来展示呢?这个问题请好好思考一下? 这里我个人的想法是,先更新API接口,后续再做进一步的数据展示和UI,毕竟不能给你一种一蹴而就的感觉,否则你会觉得无从下手,就好像,看到网络别人的功能写的很好,千辛万苦拿到代码之后,却看不懂,只能古逼的一行一行去运行调试,理解意思,这种情况是存在的。 所以,这一篇文章,我先尽量不改动UI,只更新API和数据。

① 改变请求地址

打开ServiceGenerator.java

为了避免不必要的麻烦,我特地将新的地址加在后面,而不是直接替换掉,代码如下:(PS:相信你改起来是很快的)

 private static String urlType(int type){
        switch (type){
            case 0://和风天气
                BASE_URL = "https://free-api.heweather.net";//S6版本接口地址
                break;
            case 1://必应每日一图
                BASE_URL = "https://cn.bing.com";
                break;
            case 2://搜索城市
                BASE_URL = "https://search.heweather.net";
                break;
            case 3://和风天气  新增
                BASE_URL = "https://devapi.heweather.net";//V7版本接口地址
                break;
            case 4://搜索城市  新增
                BASE_URL = "https://geoapi.heweather.net";//V7版本下的搜索城市地址
                break;
        }
        return BASE_URL;
    }

② 创建的数据Bean和API接口

打开ApiService.java,增加新的接口,有以下七个

1. 实况天气API
	/**
     * 实况天气 
     * @param location 城市名
     * @return 返回实况天气数据
     */
    @GET("/v7/weather/now?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<NowResponse> nowWeather(@Query("location") String location);

把请求URL中的KEY更换成你自己的KEY,虽然你用我的KEY我也没啥意见。。。

NowResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;
/**
 * 今日天气数据实体
 */
public class NowResponse {

    /**
     * code : 200
     * updateTime : 2020-07-15T08:51+08:00
     * fxLink : http://hfx.link/2ax1
     * now : {"obsTime":"2020-07-15T07:35+08:00","temp":"27","feelsLike":"29","icon":"100","text":"晴","wind360":"209","windDir":"西南风","windScale":"1","windSpeed":"4","humidity":"67","precip":"0.0","pressure":"1001","vis":"11","cloud":"0","dew":"20"}
     * refer : {"sources":["Weather China"],"license":["no commercial use"]}
     */

    private String code;
    private String updateTime;
    private String fxLink;
    private NowBean now;
    private ReferBean refer;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public String getFxLink() {
        return fxLink;
    }

    public void setFxLink(String fxLink) {
        this.fxLink = fxLink;
    }

    public NowBean getNow() {
        return now;
    }

    public void setNow(NowBean now) {
        this.now = now;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public static class NowBean {
        /**
         * obsTime : 2020-07-15T07:35+08:00
         * temp : 27
         * feelsLike : 29
         * icon : 100
         * text : 晴
         * wind360 : 209
         * windDir : 西南风
         * windScale : 1
         * windSpeed : 4
         * humidity : 67
         * precip : 0.0
         * pressure : 1001
         * vis : 11
         * cloud : 0
         * dew : 20
         */

        private String obsTime;
        private String temp;
        private String feelsLike;
        private String icon;
        private String text;
        private String wind360;
        private String windDir;
        private String windScale;
        private String windSpeed;
        private String humidity;
        private String precip;
        private String pressure;
        private String vis;
        private String cloud;
        private String dew;

        public String getObsTime() {
            return obsTime;
        }

        public void setObsTime(String obsTime) {
            this.obsTime = obsTime;
        }

        public String getTemp() {
            return temp;
        }

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

        public String getFeelsLike() {
            return feelsLike;
        }

        public void setFeelsLike(String feelsLike) {
            this.feelsLike = feelsLike;
        }

        public String getIcon() {
            return icon;
        }

        public void setIcon(String icon) {
            this.icon = icon;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public String getWind360() {
            return wind360;
        }

        public void setWind360(String wind360) {
            this.wind360 = wind360;
        }

        public String getWindDir() {
            return windDir;
        }

        public void setWindDir(String windDir) {
            this.windDir = windDir;
        }

        public String getWindScale() {
            return windScale;
        }

        public void setWindScale(String windScale) {
            this.windScale = windScale;
        }

        public String getWindSpeed() {
            return windSpeed;
        }

        public void setWindSpeed(String windSpeed) {
            this.windSpeed = windSpeed;
        }

        public String getHumidity() {
            return humidity;
        }

        public void setHumidity(String humidity) {
            this.humidity = humidity;
        }

        public String getPrecip() {
            return precip;
        }

        public void setPrecip(String precip) {
            this.precip = precip;
        }

        public String getPressure() {
            return pressure;
        }

        public void setPressure(String pressure) {
            this.pressure = pressure;
        }

        public String getVis() {
            return vis;
        }

        public void setVis(String vis) {
            this.vis = vis;
        }

        public String getCloud() {
            return cloud;
        }

        public void setCloud(String cloud) {
            this.cloud = cloud;
        }

        public String getDew() {
            return dew;
        }

        public void setDew(String dew) {
            this.dew = dew;
        }
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }
}
2. 天气预报API
	/**
     * 天气预报  因为是开发者所以最多可以获得15天的数据,但是如果你是普通用户,那么最多只能获得三天的数据
     * 分为 3天、7天、10天、15天 四种情况,这是时候就需要动态的改变请求的url
     * @param type  天数类型  传入3d / 7d / 10d / 15d  通过Path拼接到请求的url里面
     * @param location 城市名
     * @return 返回天气预报数据
     */
    @GET("/v7/weather/{type}?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<DailyResponse> dailyWeather(@Path("type") String type,@Query("location") String location);

DailyResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;
/**
 * 天气预报数据实体
 */
public class DailyResponse {

    /**
     * code : 200
     * updateTime : 2020-07-15T08:55+08:00
     * fxLink : http://hfx.link/2ax1
     * daily : [{"fxDate":"2020-07-15","sunrise":"04:59","sunset":"19:41","moonrise":"00:44","moonset":"14:35","moonPhase":"残月","tempMax":"32","tempMin":"22","iconDay":"101","textDay":"多云","iconNight":"150","textNight":"晴","wind360Day":"242","windDirDay":"西南风","windScaleDay":"1-2","windSpeedDay":"9","wind360Night":"202","windDirNight":"西南风","windScaleNight":"1-2","windSpeedNight":"4","humidity":"49","precip":"0.0","pressure":"996","vis":"25","cloud":"25","uvIndex":"11"},{"fxDate":"2020-07-16","sunrise":"05:00","sunset":"19:40","moonrise":"01:13","moonset":"15:36","moonPhase":"残月","tempMax":"32","tempMin":"24","iconDay":"101","textDay":"多云","iconNight":"302","textNight":"雷阵雨","wind360Day":"232","windDirDay":"西南风","windScaleDay":"1-2","windSpeedDay":"7","wind360Night":"179","windDirNight":"南风","windScaleNight":"1-2","windSpeedNight":"10","humidity":"50","precip":"0.0","pressure":"996","vis":"25","cloud":"25","uvIndex":"6"},{"fxDate":"2020-07-17","sunrise":"05:01","sunset":"19:39","moonrise":"01:46","moonset":"16:38","moonPhase":"残月","tempMax":"30","tempMin":"23","iconDay":"302","textDay":"雷阵雨","iconNight":"302","textNight":"雷阵雨","wind360Day":"186","windDirDay":"南风","windScaleDay":"3-4","windSpeedDay":"14","wind360Night":"129","windDirNight":"东南风","windScaleNight":"1-2","windSpeedNight":"4","humidity":"75","precip":"1.0","pressure":"997","vis":"24","cloud":"55","uvIndex":"1"},{"fxDate":"2020-07-18","sunrise":"05:02","sunset":"19:39","moonrise":"02:24","moonset":"17:40","moonPhase":"残月","tempMax":"29","tempMin":"21","iconDay":"302","textDay":"雷阵雨","iconNight":"305","textNight":"小雨","wind360Day":"175","windDirDay":"南风","windScaleDay":"1-2","windSpeedDay":"4","wind360Night":"60","windDirNight":"东北风","windScaleNight":"1-2","windSpeedNight":"4","humidity":"81","precip":"0.0","pressure":"997","vis":"7","cloud":"24","uvIndex":"7"},{"fxDate":"2020-07-19","sunrise":"05:02","sunset":"19:38","moonrise":"03:12","moonset":"18:38","moonPhase":"残月","tempMax":"27","tempMin":"21","iconDay":"305","textDay":"小雨","iconNight":"302","textNight":"雷阵雨","wind360Day":"43","windDirDay":"东北风","windScaleDay":"1-2","windSpeedDay":"9","wind360Night":"243","windDirNight":"西南风","windScaleNight":"1-2","windSpeedNight":"1","humidity":"69","precip":"0.0","pressure":"996","vis":"24","cloud":"25","uvIndex":"5"},{"fxDate":"2020-07-20","sunrise":"05:03","sunset":"19:37","moonrise":"04:06","moonset":"19:33","moonPhase":"新月","tempMax":"32","tempMin":"22","iconDay":"101","textDay":"多云","iconNight":"101","textNight":"多云","wind360Day":"243","windDirDay":"西南风","windScaleDay":"1-2","windSpeedDay":"8","wind360Night":"357","windDirNight":"北风","windScaleNight":"1-2","windSpeedNight":"5","humidity":"55","precip":"0.0","pressure":"995","vis":"24","cloud":"0","uvIndex":"10"},{"fxDate":"2020-07-21","sunrise":"05:04","sunset":"19:36","moonrise":"05:10","moonset":"20:20","moonPhase":"峨眉月","tempMax":"33","tempMin":"22","iconDay":"100","textDay":"晴","iconNight":"150","textNight":"晴","wind360Day":"2","windDirDay":"北风","windScaleDay":"1-2","windSpeedDay":"6","wind360Night":"358","windDirNight":"北风","windScaleNight":"1-2","windSpeedNight":"2","humidity":"38","precip":"0.0","pressure":"999","vis":"25","cloud":"1","uvIndex":"10"}]
     * refer : {"sources":["Weather China"],"license":["no commercial use"]}
     */

    private String code;
    private String updateTime;
    private String fxLink;
    private ReferBean refer;
    private List<DailyBean> daily;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public String getFxLink() {
        return fxLink;
    }

    public void setFxLink(String fxLink) {
        this.fxLink = fxLink;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public List<DailyBean> getDaily() {
        return daily;
    }

    public void setDaily(List<DailyBean> daily) {
        this.daily = daily;
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }

    public static class DailyBean {
        /**
         * fxDate : 2020-07-15
         * sunrise : 04:59
         * sunset : 19:41
         * moonrise : 00:44
         * moonset : 14:35
         * moonPhase : 残月
         * tempMax : 32
         * tempMin : 22
         * iconDay : 101
         * textDay : 多云
         * iconNight : 150
         * textNight : 晴
         * wind360Day : 242
         * windDirDay : 西南风
         * windScaleDay : 1-2
         * windSpeedDay : 9
         * wind360Night : 202
         * windDirNight : 西南风
         * windScaleNight : 1-2
         * windSpeedNight : 4
         * humidity : 49
         * precip : 0.0
         * pressure : 996
         * vis : 25
         * cloud : 25
         * uvIndex : 11
         */

        private String fxDate;
        private String sunrise;
        private String sunset;
        private String moonrise;
        private String moonset;
        private String moonPhase;
        private String tempMax;
        private String tempMin;
        private String iconDay;
        private String textDay;
        private String iconNight;
        private String textNight;
        private String wind360Day;
        private String windDirDay;
        private String windScaleDay;
        private String windSpeedDay;
        private String wind360Night;
        private String windDirNight;
        private String windScaleNight;
        private String windSpeedNight;
        private String humidity;
        private String precip;
        private String pressure;
        private String vis;
        private String cloud;
        private String uvIndex;

        public String getFxDate() {
            return fxDate;
        }

        public void setFxDate(String fxDate) {
            this.fxDate = fxDate;
        }

        public String getSunrise() {
            return sunrise;
        }

        public void setSunrise(String sunrise) {
            this.sunrise = sunrise;
        }

        public String getSunset() {
            return sunset;
        }

        public void setSunset(String sunset) {
            this.sunset = sunset;
        }

        public String getMoonrise() {
            return moonrise;
        }

        public void setMoonrise(String moonrise) {
            this.moonrise = moonrise;
        }

        public String getMoonset() {
            return moonset;
        }

        public void setMoonset(String moonset) {
            this.moonset = moonset;
        }

        public String getMoonPhase() {
            return moonPhase;
        }

        public void setMoonPhase(String moonPhase) {
            this.moonPhase = moonPhase;
        }

        public String getTempMax() {
            return tempMax;
        }

        public void setTempMax(String tempMax) {
            this.tempMax = tempMax;
        }

        public String getTempMin() {
            return tempMin;
        }

        public void setTempMin(String tempMin) {
            this.tempMin = tempMin;
        }

        public String getIconDay() {
            return iconDay;
        }

        public void setIconDay(String iconDay) {
            this.iconDay = iconDay;
        }

        public String getTextDay() {
            return textDay;
        }

        public void setTextDay(String textDay) {
            this.textDay = textDay;
        }

        public String getIconNight() {
            return iconNight;
        }

        public void setIconNight(String iconNight) {
            this.iconNight = iconNight;
        }

        public String getTextNight() {
            return textNight;
        }

        public void setTextNight(String textNight) {
            this.textNight = textNight;
        }

        public String getWind360Day() {
            return wind360Day;
        }

        public void setWind360Day(String wind360Day) {
            this.wind360Day = wind360Day;
        }

        public String getWindDirDay() {
            return windDirDay;
        }

        public void setWindDirDay(String windDirDay) {
            this.windDirDay = windDirDay;
        }

        public String getWindScaleDay() {
            return windScaleDay;
        }

        public void setWindScaleDay(String windScaleDay) {
            this.windScaleDay = windScaleDay;
        }

        public String getWindSpeedDay() {
            return windSpeedDay;
        }

        public void setWindSpeedDay(String windSpeedDay) {
            this.windSpeedDay = windSpeedDay;
        }

        public String getWind360Night() {
            return wind360Night;
        }

        public void setWind360Night(String wind360Night) {
            this.wind360Night = wind360Night;
        }

        public String getWindDirNight() {
            return windDirNight;
        }

        public void setWindDirNight(String windDirNight) {
            this.windDirNight = windDirNight;
        }

        public String getWindScaleNight() {
            return windScaleNight;
        }

        public void setWindScaleNight(String windScaleNight) {
            this.windScaleNight = windScaleNight;
        }

        public String getWindSpeedNight() {
            return windSpeedNight;
        }

        public void setWindSpeedNight(String windSpeedNight) {
            this.windSpeedNight = windSpeedNight;
        }

        public String getHumidity() {
            return humidity;
        }

        public void setHumidity(String humidity) {
            this.humidity = humidity;
        }

        public String getPrecip() {
            return precip;
        }

        public void setPrecip(String precip) {
            this.precip = precip;
        }

        public String getPressure() {
            return pressure;
        }

        public void setPressure(String pressure) {
            this.pressure = pressure;
        }

        public String getVis() {
            return vis;
        }

        public void setVis(String vis) {
            this.vis = vis;
        }

        public String getCloud() {
            return cloud;
        }

        public void setCloud(String cloud) {
            this.cloud = cloud;
        }

        public String getUvIndex() {
            return uvIndex;
        }

        public void setUvIndex(String uvIndex) {
            this.uvIndex = uvIndex;
        }
    }
}
3. 逐小时预报API
	/**
     * 逐小时预报(未来24小时)之前是逐三小时预报
     * @param location  城市名
     * @return 返回逐小时数据
     */
    @GET("/v7/weather/24h?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<HourlyResponse> hourlyWeather(@Query("location") String location);

HourlyResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;
/**
 * 逐小时天气数据实体
 */
public class HourlyResponse {
    /**
     * code : 200
     * updateTime : 2020-07-15T08:57+08:00
     * fxLink : http://hfx.link/2ax1
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* * hourly : [{"fxTime":"2020-07-15T10:00+08:00","temp":"28","icon":"100","text":"晴","wind360":"194","windDir":"西南风","windScale":"1-2","windSpeed":"10","humidity":"40","pop":"0","precip":"0.0","pressure":"995","cloud":"0","dew":"19"},{"fxTime":"2020-07-15T11:00+08:00","temp":"29","icon":"100","text":"晴","wind360":"195","windDir":"西南风","windScale":"1-2","windSpeed":"6","humidity":"35","pop":"0","precip":"0.0","pressure":"995","cloud":"1","dew":"19"},{"fxTime":"2020-07-15T12:00+08:00","temp":"30","icon":"100","text":"晴","wind360":"199","windDir":"西南风","windScale":"1-2","windSpeed":"8","humidity":"33","pop":"0","precip":"0.0","pressure":"995","cloud":"1","dew":"19"},{"fxTime":"2020-07-15T13:00+08:00","temp":"31","icon":"100","text":"晴","wind360":"203","windDir":"西南风","windScale":"1-2","windSpeed":"7","humidity":"31","pop":"0","precip":"0.0","pressure":"996","cloud":"2","dew":"19"},{"fxTime":"2020-07-15T14:00+08:00","temp":"31","icon":"100","text":"晴","wind360":"257","windDir":"西南风","windScale":"1-2","windSpeed":"6","humidity":"29","pop":"0","precip":"0.0","pressure":"997","cloud":"2","dew":"19"},{"fxTime":"2020-07-15T15:00+08:00","temp":"31","icon":"100","text":"晴","wind360":"245","windDir":"西南风","windScale":"1-2","windSpeed":"2","humidity":"31","pop":"0","precip":"0.0","pressure":"997","cloud":"7","dew":"19"},{"fxTime":"2020-07-15T16:00+08:00","temp":"31","icon":"100","text":"晴","wind360":"199","windDir":"西南风","windScale":"1-2","windSpeed":"2","humidity":"32","pop":"0","precip":"0.0","pressure":"997","cloud":"13","dew":"19"},{"fxTime":"2020-07-15T17:00+08:00","temp":"31","icon":"101","text":"多云","wind360":"231","windDir":"西南风","windScale":"1-2","windSpeed":"7","humidity":"33","pop":"0","precip":"0.0","pressure":"997","cloud":"18","dew":"18"},{"fxTime":"2020-07-15T18:00+08:00","temp":"30","icon":"100","text":"晴","wind360":"249","windDir":"西南风","windScale":"1-2","windSpeed":"10","humidity":"38","pop":"0","precip":"0.0","pressure":"996","cloud":"18","dew":"19"},{"fxTime":"2020-07-15T19:00+08:00","temp":"28","icon":"100","text":"晴","wind360":"234","windDir":"西南风","windScale":"1-2","windSpeed":"5","humidity":"43","pop":"0","precip":"0.0","pressure":"996","cloud":"18","dew":"20"},{"fxTime":"2020-07-15T20:00+08:00","temp":"27","icon":"100","text":"晴","wind360":"206","windDir":"西南风","windScale":"1-2","windSpeed":"9","humidity":"47","pop":"0","precip":"0.0","pressure":"997","cloud":"18","dew":"20"},{"fxTime":"2020-07-15T21:00+08:00","temp":"26","icon":"100","text":"晴","wind360":"198","windDir":"西南风","windScale":"1-2","windSpeed":"6","humidity":"51","pop":"0","precip":"0.0","pressure":"997","cloud":"12","dew":"20"},{"fxTime":"2020-07-15T22:00+08:00","temp":"26","icon":"100","text":"晴","wind360":"249","windDir":"西南风","windScale":"1-2","windSpeed":"5","humidity":"54","pop":"0","precip":"0.0","pressure":"997","cloud":"6","dew":"20"},{"fxTime":"2020-07-15T23:00+08:00","temp":"25","icon":"100","text":"晴","wind360":"248","windDir":"西南风","windScale":"1-2","windSpeed":"4","humidity":"58","pop":"0","precip":"0.0","pressure":"997","cloud":"0","dew":"20"},{"fxTime":"2020-07-16T00:00+08:00","temp":"24","icon":"100","text":"晴","wind360":"230","windDir":"西南风","windScale":"1-2","windSpeed":"6","humidity":"60","pop":"0","precip":"0.0","pressure":"997","cloud":"1","dew":"19"},{"fxTime":"2020-07-16T01:00+08:00","temp":"24","icon":"100","text":"晴","wind360":"255","windDir":"西南风","windScale":"1-2","windSpeed":"4","humidity":"62","pop":"0","precip":"0.0","pressure":"997","cloud":"3","dew":"19"},{"fxTime":"2020-07-16T02:00+08:00","temp":"23","icon":"100","text":"晴","wind360":"230","windDir":"西南风","windScale":"1-2","windSpeed":"7","humidity":"63","pop":"0","precip":"0.0","pressure":"997","cloud":"4","dew":"20"},{"fxTime":"2020-07-16T03:00+08:00","temp":"23","icon":"100","text":"晴","wind360":"209","windDir":"西南风","windScale":"1-2","windSpeed":"1","humidity":"65","pop":"0","precip":"0.0","pressure":"997","cloud":"4","dew":"20"},{"fxTime":"2020-07-16T04:00+08:00","temp":"23","icon":"100","text":"晴","wind360":"213","windDir":"西南风","windScale":"1-2","windSpeed":"8","humidity":"66","pop":"0","precip":"0.0","pressure":"996","cloud":"4","dew":"20"},{"fxTime":"2020-07-16T05:00+08:00","temp":"22","icon":"100","text":"晴","wind360":"193","windDir":"西南风","windScale":"1-2","windSpeed":"7","humidity":"67","pop":"0","precip":"0.0","pressure":"995","cloud":"3","dew":"20"},{"fxTime":"2020-07-16T06:00+08:00","temp":"23","icon":"101","text":"多云","wind360":"216","windDir":"西南风","windScale":"1-2","windSpeed":"11","humidity":"70","pop":"0","precip":"0.0","pressure":"994","cloud":"20","dew":"21"},{"fxTime":"2020-07-16T07:00+08:00","temp":"25","icon":"101","text":"多云","wind360":"229","windDir":"西南风","windScale":"1-2","windSpeed":"11","humidity":"73","pop":"0","precip":"0.0","pressure":"994","cloud":"37","dew":"21"},{"fxTime":"2020-07-16T08:00+08:00","temp":"26","icon":"101","text":"多云","wind360":"200","windDir":"西南风","windScale":"1-2","windSpeed":"4","humidity":"77","pop":"0","precip":"0.0","pressure":"993","cloud":"54","dew":"21"},{"fxTime":"2020-07-16T09:00+08:00","temp":"28","icon":"101","text":"多云","wind360":"200","windDir":"西南风","windScale":"1-2","windSpeed":"4","humidity":"65","pop":"0","precip":"0.0","pressure":"993","cloud":"53","dew":"21"}]
*/
     * refer : {"sources":["Weather China"],"license":["no commercial use"]}
     */

    private String code;
    private String updateTime;
    private String fxLink;
    private ReferBean refer;
    private List<HourlyBean> hourly;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public String getFxLink() {
        return fxLink;
    }

    public void setFxLink(String fxLink) {
        this.fxLink = fxLink;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public List<HourlyBean> getHourly() {
        return hourly;
    }

    public void setHourly(List<HourlyBean> hourly) {
        this.hourly = hourly;
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }

    public static class HourlyBean {
        /**
         * fxTime : 2020-07-15T10:00+08:00
         * temp : 28
         * icon : 100
         * text : 晴
         * wind360 : 194
         * windDir : 西南风
         * windScale : 1-2
         * windSpeed : 10
         * humidity : 40
         * pop : 0
         * precip : 0.0
         * pressure : 995
         * cloud : 0
         * dew : 19
         */

        private String fxTime;
        private String temp;
        private String icon;
        private String text;
        private String wind360;
        private String windDir;
        private String windScale;
        private String windSpeed;
        private String humidity;
        private String pop;
        private String precip;
        private String pressure;
        private String cloud;
        private String dew;

        public String getFxTime() {
            return fxTime;
        }

        public void setFxTime(String fxTime) {
            this.fxTime = fxTime;
        }

        public String getTemp() {
            return temp;
        }

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

        public String getIcon() {
            return icon;
        }

        public void setIcon(String icon) {
            this.icon = icon;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public String getWind360() {
            return wind360;
        }

        public void setWind360(String wind360) {
            this.wind360 = wind360;
        }

        public String getWindDir() {
            return windDir;
        }

        public void setWindDir(String windDir) {
            this.windDir = windDir;
        }

        public String getWindScale() {
            return windScale;
        }

        public void setWindScale(String windScale) {
            this.windScale = windScale;
        }

        public String getWindSpeed() {
            return windSpeed;
        }

        public void setWindSpeed(String windSpeed) {
            this.windSpeed = windSpeed;
        }

        public String getHumidity() {
            return humidity;
        }

        public void setHumidity(String humidity) {
            this.humidity = humidity;
        }

        public String getPop() {
            return pop;
        }

        public void setPop(String pop) {
            this.pop = pop;
        }

        public String getPrecip() {
            return precip;
        }

        public void setPrecip(String precip) {
            this.precip = precip;
        }

        public String getPressure() {
            return pressure;
        }

        public void setPressure(String pressure) {
            this.pressure = pressure;
        }

        public String getCloud() {
            return cloud;
        }

        public void setCloud(String cloud) {
            this.cloud = cloud;
        }

        public String getDew() {
            return dew;
        }

        public void setDew(String dew) {
            this.dew = dew;
        }
    }
}
4. 空气质量API
	/**
     * 当天空气质量
     * @param location 城市名
     * @return 返回当天空气质量数据
     */
    @GET("/v7/air/now?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<AirNowResponse> airNowWeather(@Query("location") String location);

AirNowResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;

/**
 * 当天空气质量数据实体
 */
public class AirNowResponse {

    /**
     * code : 200
     * updateTime : 2020-07-15T09:34+08:00
     * fxLink : http://hfx.link/2ax4
     * now : {"pubTime":"2020-07-15T09:00+08:00","aqi":"49","category":"优","primary":"NA","pm10":"49","pm2p5":"29","no2":"20","so2":"3","co":"0.6","o3":"84"}
     * station : [{"pubTime":"2020-07-15T09:00+08:00","name":"万寿西宫","id":"CNA1001","aqi":"68","level":"2","category":"良","primary":"PM2.5","pm10":"66","pm2p5":"49","no2":"29","so2":"3","co":"0.7","o3":"81"},{"pubTime":"2020-07-15T09:00+08:00","name":"定陵","id":"CNA1002","aqi":"36","level":"1","category":"优","primary":"NA","pm10":"36","pm2p5":"15","no2":"11","so2":"3","co":"0.4","o3":"84"},{"pubTime":"2020-07-15T09:00+08:00","name":"东四","id":"CNA1003","aqi":"46","level":"1","category":"优","primary":"NA","pm10":"44","pm2p5":"32","no2":"21","so2":"3","co":"0.9","o3":"95"},{"pubTime":"2020-07-15T09:00+08:00","name":"天坛","id":"CNA1004","aqi":"57","level":"2","category":"良","primary":"PM2.5","pm10":"56","pm2p5":"40","no2":"18","so2":"1","co":"0.7","o3":"96"},{"pubTime":"2020-07-15T09:00+08:00","name":"农展馆","id":"CNA1005","aqi":"55","level":"2","category":"良","primary":"PM10","pm10":"59","pm2p5":"35","no2":"26","so2":"3","co":"0.7","o3":"79"},{"pubTime":"2020-07-15T09:00+08:00","name":"官园","id":"CNA1006","aqi":"53","level":"2","category":"良","primary":"PM2.5","pm10":"52","pm2p5":"37","no2":"24","so2":"1","co":"0.6","o3":"91"},{"pubTime":"2020-07-15T09:00+08:00","name":"海淀区万柳","id":"CNA1007","aqi":"48","level":"1","category":"优","primary":"NA","pm10":"48","pm2p5":"28","no2":"28","so2":"1","co":"0.6","o3":"79"},{"pubTime":"2020-07-15T09:00+08:00","name":"顺义新城","id":"CNA1008","aqi":"46","level":"1","category":"优","primary":"NA","pm10":"46","pm2p5":"22","no2":"15","so2":"3","co":"0.5","o3":"85"},{"pubTime":"2020-07-15T09:00+08:00","name":"怀柔镇","id":"CNA1009","aqi":"43","level":"1","category":"优","primary":"NA","pm10":"43","pm2p5":"22","no2":"18","so2":"3","co":"0.5","o3":"78"},{"pubTime":"2020-07-15T09:00+08:00","name":"昌平镇","id":"CNA1010","aqi":"53","level":"2","category":"良","primary":"PM10","pm10":"56","pm2p5":"23","no2":"21","so2":"1","co":"0.5","o3":"68"},{"pubTime":"2020-07-15T09:00+08:00","name":"奥体中心","id":"CNA1011","aqi":"44","level":"1","category":"优","primary":"NA","pm10":"44","pm2p5":"22","no2":"17","so2":"3","co":"0.5","o3":"89"},{"pubTime":"2020-07-15T09:00+08:00","name":"古城","id":"CNA1012","aqi":"32","level":"1","category":"优","primary":"NA","pm10":"28","pm2p5":"22","no2":"11","so2":"3","co":"0.5","o3":"80"}]
     * refer : {"sources":["cnemc"],"license":["no commercial use"]}
     */

    private String code;
    private String updateTime;
    private String fxLink;
    private NowBean now;
    private ReferBean refer;
    private List<StationBean> station;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public String getFxLink() {
        return fxLink;
    }

    public void setFxLink(String fxLink) {
        this.fxLink = fxLink;
    }

    public NowBean getNow() {
        return now;
    }

    public void setNow(NowBean now) {
        this.now = now;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public List<StationBean> getStation() {
        return station;
    }

    public void setStation(List<StationBean> station) {
        this.station = station;
    }

    public static class NowBean {
        /**
         * pubTime : 2020-07-15T09:00+08:00
         * aqi : 49
         * category : 优
         * primary : NA
         * pm10 : 49
         * pm2p5 : 29
         * no2 : 20
         * so2 : 3
         * co : 0.6
         * o3 : 84
         */

        private String pubTime;
        private String aqi;
        private String category;
        private String primary;
        private String pm10;
        private String pm2p5;
        private String no2;
        private String so2;
        private String co;
        private String o3;

        public String getPubTime() {
            return pubTime;
        }

        public void setPubTime(String pubTime) {
            this.pubTime = pubTime;
        }

        public String getAqi() {
            return aqi;
        }

        public void setAqi(String aqi) {
            this.aqi = aqi;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

        public String getPrimary() {
            return primary;
        }

        public void setPrimary(String primary) {
            this.primary = primary;
        }

        public String getPm10() {
            return pm10;
        }

        public void setPm10(String pm10) {
            this.pm10 = pm10;
        }

        public String getPm2p5() {
            return pm2p5;
        }

        public void setPm2p5(String pm2p5) {
            this.pm2p5 = pm2p5;
        }

        public String getNo2() {
            return no2;
        }

        public void setNo2(String no2) {
            this.no2 = no2;
        }

        public String getSo2() {
            return so2;
        }

        public void setSo2(String so2) {
            this.so2 = so2;
        }

        public String getCo() {
            return co;
        }

        public void setCo(String co) {
            this.co = co;
        }

        public String getO3() {
            return o3;
        }

        public void setO3(String o3) {
            this.o3 = o3;
        }
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }

    public static class StationBean {
        /**
         * pubTime : 2020-07-15T09:00+08:00
         * name : 万寿西宫
         * id : CNA1001
         * aqi : 68
         * level : 2
         * category : 良
         * primary : PM2.5
         * pm10 : 66
         * pm2p5 : 49
         * no2 : 29
         * so2 : 3
         * co : 0.7
         * o3 : 81
         */

        private String pubTime;
        private String name;
        private String id;
        private String aqi;
        private String level;
        private String category;
        private String primary;
        private String pm10;
        private String pm2p5;
        private String no2;
        private String so2;
        private String co;
        private String o3;

        public String getPubTime() {
            return pubTime;
        }

        public void setPubTime(String pubTime) {
            this.pubTime = pubTime;
        }

        public String getName() {
            return name;
        }

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

        public String getId() {
            return id;
        }

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

        public String getAqi() {
            return aqi;
        }

        public void setAqi(String aqi) {
            this.aqi = aqi;
        }

        public String getLevel() {
            return level;
        }

        public void setLevel(String level) {
            this.level = level;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

        public String getPrimary() {
            return primary;
        }

        public void setPrimary(String primary) {
            this.primary = primary;
        }

        public String getPm10() {
            return pm10;
        }

        public void setPm10(String pm10) {
            this.pm10 = pm10;
        }

        public String getPm2p5() {
            return pm2p5;
        }

        public void setPm2p5(String pm2p5) {
            this.pm2p5 = pm2p5;
        }

        public String getNo2() {
            return no2;
        }

        public void setNo2(String no2) {
            this.no2 = no2;
        }

        public String getSo2() {
            return so2;
        }

        public void setSo2(String so2) {
            this.so2 = so2;
        }

        public String getCo() {
            return co;
        }

        public void setCo(String co) {
            this.co = co;
        }

        public String getO3() {
            return o3;
        }

        public void setO3(String o3) {
            this.o3 = o3;
        }
    }
}
5. 生活指数API
	/**
     * 生活指数
     * @param type 可以控制定向获取那几项数据 全部数据 0, 运动指数	1 ,洗车指数	2 ,穿衣指数	3 ,
     *             钓鱼指数	4 ,紫外线指数  5 ,旅游指数  6,花粉过敏指数	7,舒适度指数	8,
     *             感冒指数	9 ,空气污染扩散条件指数	10 ,空调开启指数	 11 ,太阳镜指数	12 ,
     *             化妆指数  13 ,晾晒指数  14 ,交通指数  15 ,防晒指数	16
     * @param location 城市名
     * @return 返回当前生活指数数据
     * @return
     */
    @GET("/v7/indices/1d?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<LifestyleResponse> Lifestyle(@Query("type") String type,
                                      @Query("location") String location);

LifestyleResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;
/**
 * 生活指数
 */
public class LifestyleResponse {

    /**
     * code : 200
     * updateTime : 2020-07-15T09:10+08:00
     * fxLink : http://hfx.link/2ax2
     * daily : [{"date":"2020-07-15","type":"13","name":"化妆指数","level":"4","category":"防脱水防晒","text":"天气炎热,用防脱水防晒指数高的化妆品,少用粉底,常补粉。"},{"date":"2020-07-15","type":"6","name":"旅游指数","level":"1","category":"适宜","text":"天气较好,但丝毫不会影响您的心情。微风,虽天气稍热,却仍适宜旅游,不要错过机会呦!"},{"date":"2020-07-15","type":"14","name":"晾晒指数","level":"2","category":"适宜","text":"天气不错,适宜晾晒。赶紧把久未见阳光的衣物搬出来吸收一下太阳的味道吧!"},{"date":"2020-07-15","type":"15","name":"交通指数","level":"1","category":"良好","text":"天气较好,路面干燥,交通气象条件良好,车辆可以正常行驶。"},{"date":"2020-07-15","type":"10","name":"空气污染扩散条件指数","level":"2","category":"中","text":"气象条件对空气污染物稀释、扩散和清除无明显影响。"},{"date":"2020-07-15","type":"3","name":"穿衣指数","level":"7","category":"炎热","text":"天气炎热,建议着短衫、短裙、短裤、薄型T恤衫等清凉夏季服装。"},{"date":"2020-07-15","type":"16","name":"防晒指数","level":"2","category":"极强","text":"紫外辐射极强,应特别加强防护,建议涂擦SPF20以上,PA++的防晒护肤品,并随时补涂。"},{"date":"2020-07-15","type":"4","name":"钓鱼指数","level":"2","category":"较适宜","text":"较适合垂钓,但风力稍大,会对垂钓产生一定的影响。"},{"date":"2020-07-15","type":"5","name":"紫外线指数","level":"5","category":"很强","text":"紫外线辐射极强,建议涂擦SPF20以上、PA++的防晒护肤品,尽量避免暴露于日光下。"},{"date":"2020-07-15","type":"11","name":"空调开启指数","level":"2","category":"部分时间开启","text":"天气热,到中午的时候您将会感到有点热,因此建议在午后较热时开启制冷空调。"},{"date":"2020-07-15","type":"12","name":"太阳镜指数","level":"4","category":"很必要","text":"白天虽有白云遮挡,但太阳辐射仍很强,建议佩戴透射比2级且标注UV400的遮阳镜"},{"date":"2020-07-15","type":"7","name":"过敏指数","level":"2","category":"不易发","text":"天气条件不易诱发过敏,除特殊体质外,无需担心过敏问题。"},{"date":"2020-07-15","type":"8","name":"舒适度指数","level":"3","category":"较不舒适","text":"白天天气多云,同时会感到有些热,不很舒适。"},{"date":"2020-07-15","type":"9","name":"感冒指数","level":"1","category":"少发","text":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。"},{"date":"2020-07-15","type":"2","name":"洗车指数","level":"2","category":"较适宜","text":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"},{"date":"2020-07-15","type":"1","name":"运动指数","level":"2","category":"较适宜","text":"天气较好,较适宜进行各种运动,但因天气热,请适当减少运动时间,降低运动强度。"}]
     * refer : {"sources":["Weather China"],"license":["no commercial use"]}
     */

    private String code;
    private String updateTime;
    private String fxLink;
    private ReferBean refer;
    private List<DailyBean> daily;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public String getFxLink() {
        return fxLink;
    }

    public void setFxLink(String fxLink) {
        this.fxLink = fxLink;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public List<DailyBean> getDaily() {
        return daily;
    }

    public void setDaily(List<DailyBean> daily) {
        this.daily = daily;
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }

    public static class DailyBean {
        /**
         * date : 2020-07-15
         * type : 13
         * name : 化妆指数
         * level : 4
         * category : 防脱水防晒
         * text : 天气炎热,用防脱水防晒指数高的化妆品,少用粉底,常补粉。
         */

        private String date;
        private String type;
        private String name;
        private String level;
        private String category;
        private String text;

        public String getDate() {
            return date;
        }

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

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

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

        public String getLevel() {
            return level;
        }

        public void setLevel(String level) {
            this.level = level;
        }

        public String getCategory() {
            return category;
        }

        public void setCategory(String category) {
            this.category = category;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }
    }
}
6. 搜索城市API
	/**
     * 搜索城市  V7版本  模糊搜索,国内范围 返回10条数据
     *
     * @param location 城市名
     * @param mode     exact 精准搜索  fuzzy 模糊搜索
     * @return
     */
    @GET("/v2/city/lookup?key=3086e91d66c04ce588a7f538f917c7f4&range=cn")
    Call<NewSearchCityResponse> newSearchCity(@Query("location") String location,
                                              @Query("mode") String mode);

NewSearchCityResponse.java代码如下:

package com.llw.goodweather.bean;

import java.util.List;

public class NewSearchCityResponse {

    /**
     * status : 200
     * location : [{"name":"北京","id":"101010100","lat":"39.90498","lon":"116.40528","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"10","fxLink":"http://hfx.link/2ax1"},{"name":"朝阳","id":"101010300","lat":"39.92148","lon":"116.48641","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"15","fxLink":"http://hfx.link/2az1"},{"name":"海淀","id":"101010200","lat":"39.95607","lon":"116.31031","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"15","fxLink":"http://hfx.link/2ay1"},{"name":"丰台","id":"101010900","lat":"39.86364","lon":"116.28696","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"25","fxLink":"http://hfx.link/2b51"},{"name":"大兴","id":"101011100","lat":"39.72890","lon":"116.33803","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"25","fxLink":"http://hfx.link/2b71"},{"name":"房山","id":"101011200","lat":"39.73553","lon":"116.13916","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"23","fxLink":"http://hfx.link/2b81"},{"name":"通州","id":"101010600","lat":"39.90248","lon":"116.65859","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"23","fxLink":"http://hfx.link/2b21"},{"name":"石景山","id":"101011000","lat":"39.91460","lon":"116.19544","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"35","fxLink":"http://hfx.link/2b61"},{"name":"昌平","id":"101010700","lat":"40.21808","lon":"116.23590","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"23","fxLink":"http://hfx.link/2b31"},{"name":"顺义","id":"101010400","lat":"40.12893","lon":"116.65352","adm2":"北京","adm1":"北京","country":"中国","tz":"Asia/Shanghai","utcOffset":"+08:00","isDst":"0","type":"city","rank":"33","fxLink":"http://hfx.link/2b01"}]
     * refer : {"sources":["heweather.com"],"license":["commercial license"]}
     */

    private String status;
    private ReferBean refer;
    private List<LocationBean> location;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public ReferBean getRefer() {
        return refer;
    }

    public void setRefer(ReferBean refer) {
        this.refer = refer;
    }

    public List<LocationBean> getLocation() {
        return location;
    }

    public void setLocation(List<LocationBean> location) {
        this.location = location;
    }

    public static class ReferBean {
        private List<String> sources;
        private List<String> license;

        public List<String> getSources() {
            return sources;
        }

        public void setSources(List<String> sources) {
            this.sources = sources;
        }

        public List<String> getLicense() {
            return license;
        }

        public void setLicense(List<String> license) {
            this.license = license;
        }
    }

    public static class LocationBean {
        /**
         * name : 北京
         * id : 101010100
         * lat : 39.90498
         * lon : 116.40528
         * adm2 : 北京
         * adm1 : 北京
         * country : 中国
         * tz : Asia/Shanghai
         * utcOffset : +08:00
         * isDst : 0
         * type : city
         * rank : 10
         * fxLink : http://hfx.link/2ax1
         */

        private String name;
        private String id;
        private String lat;
        private String lon;
        private String adm2;
        private String adm1;
        private String country;
        private String tz;
        private String utcOffset;
        private String isDst;
        private String type;
        private String rank;
        private String fxLink;

        public String getName() {
            return name;
        }

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

        public String getId() {
            return id;
        }

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

        public String getLat() {
            return lat;
        }

        public void setLat(String lat) {
            this.lat = lat;
        }

        public String getLon() {
            return lon;
        }

        public void setLon(String lon) {
            this.lon = lon;
        }

        public String getAdm2() {
            return adm2;
        }

        public void setAdm2(String adm2) {
            this.adm2 = adm2;
        }

        public String getAdm1() {
            return adm1;
        }

        public void setAdm1(String adm1) {
            this.adm1 = adm1;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getTz() {
            return tz;
        }

        public void setTz(String tz) {
            this.tz = tz;
        }

        public String getUtcOffset() {
            return utcOffset;
        }

        public void setUtcOffset(String utcOffset) {
            this.utcOffset = utcOffset;
        }

        public String getIsDst() {
            return isDst;
        }

        public void setIsDst(String isDst) {
            this.isDst = isDst;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getRank() {
            return rank;
        }

        public void setRank(String rank) {
            this.rank = rank;
        }

        public String getFxLink() {
            return fxLink;
        }

        public void setFxLink(String fxLink) {
            this.fxLink = fxLink;
        }
    }
}

没有的实体你创建一个就好了,然后将代码复制进去即可。API写好之后,就可以来一个一个的改代码了。这里我没有写上热门城市的API,是因为我打算给这个里面整体改头换面一下,以适应新的V7API的使用。

③ 修改订阅器

1. 修改WeatherContract

首先当然是主页面的订阅器啦,打开WeatherContract.java 可以到看里面目前是三个方法,

除了必应的壁纸请求,其他两个就负责主页面的数据请求,这个两个方法你可以先注释掉或者删掉了。 现在增加S7版本的方法,这里面增加了六个方法

		/**
         * 搜索城市  V7版本中  需要把定位城市的id查询出来,然后通过这个id来查询详细的数据
         * @param location 城市名
         */
        public void newSearchCity(String location) {//注意这里的4表示新的搜索城市地址接口
            ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址
            service.newSearchCity(location,"exact").enqueue(new NetCallBack<NewSearchCityResponse>() {
                @Override
                public void onSuccess(Call<NewSearchCityResponse> call, Response<NewSearchCityResponse> response) {
                    if(getView() != null){
                        getView().getNewSearchCityResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getDataFailed();
                    }
                }
            });
        }


        /**
         * 实况天气  V7版本
         * @param location  城市名
         */
        public void nowWeather(String location){//这个3 表示使用新的V7API访问地址
            ApiService service = ServiceGenerator.createService(ApiService.class,3);
            service.nowWeather(location).enqueue(new NetCallBack<NowResponse>() {
                @Override
                public void onSuccess(Call<NowResponse> call, Response<NowResponse> response) {
                    if(getView() != null){
                        getView().getNowResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }

        /**
         * 天气预报  V7版本   7d 表示天气的数据 为了和之前看上去差别小一些,这里先用七天的
         * @param location   城市名
         */
        public void dailyWeather(String location){//这个3 表示使用新的V7API访问地址
            ApiService service = ServiceGenerator.createService(ApiService.class,3);
            service.dailyWeather("7d",location).enqueue(new NetCallBack<DailyResponse>() {
                @Override
                public void onSuccess(Call<DailyResponse> call, Response<DailyResponse> response) {
                    if(getView() != null){
                        getView().getDailyResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }

        /**
         * 逐小时预报(未来24小时)
         * @param location   城市名
         */
        public void hourlyWeather(String location){
            ApiService service = ServiceGenerator.createService(ApiService.class,3);
            service.hourlyWeather(location).enqueue(new NetCallBack<HourlyResponse>() {
                @Override
                public void onSuccess(Call<HourlyResponse> call, Response<HourlyResponse> response) {
                    if(getView() != null){
                        getView().getHourlyResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }

        /**
         * 当天空气质量
         * @param location   城市名
         */
        public void airNowWeather(String location){
            ApiService service = ServiceGenerator.createService(ApiService.class,3);
            service.airNowWeather(location).enqueue(new NetCallBack<AirNowResponse>() {
                @Override
                public void onSuccess(Call<AirNowResponse> call, Response<AirNowResponse> response) {
                    if(getView() != null){
                        getView().getAirNowResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }

        /**
         * 生活指数
         * @param location   城市名  type中的"1,2,3,5,6,8,9,10",表示只获取这8种类型的指数信息,同样是为了对应之前的界面UI
         */
        public void lifestyle(String location){
            ApiService service = ServiceGenerator.createService(ApiService.class,3);
            service.lifestyle("1,2,3,5,6,8,9,10",location).enqueue(new NetCallBack<LifestyleResponse>() {
                @Override
                public void onSuccess(Call<LifestyleResponse> call, Response<LifestyleResponse> response) {
                    if(getView() != null){
                        getView().getLifestyleResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }

代码如下:

		/*                以下为V7版本新增               */

        //搜索城市返回城市id  通过id才能查下面的数据,否则会提示400  V7
        void getNewSearchCityResult(Response<NewSearchCityResponse> response);
        //实况天气
        void getNowResult(Response<NowResponse> response);
        //天气预报  7天
        void getDailyResult(Response<DailyResponse> response);
        //逐小时天气预报
        void getHourlyResult(Response<HourlyResponse> response);
        //空气质量
        void getAirNowResult(Response<AirNowResponse> response);
        //生活指数
        void getLifestyleResult(Response<LifestyleResponse> response);

看我的博客你甚至都不用写代码,粘贴复制就可以了,但我还是你能自己写一下。这个时候,如果你打开MainActivity肯定是会报错的,不过不用担心,这是因为刚才新增的没有在MainActivity中实现,后面再一起实现它们,订阅器可不止一个,

2. 修改SearchCityContract

现在打开SearchCityContract.java,新增如下代码:

		/**
         * 搜索城市  V7版本中  模糊搜索  返回10条相关数据
         * @param location 城市名
         */
        public void newSearchCity(String location) {//注意这里的4表示新的搜索城市地址接口
            ApiService service = ServiceGenerator.createService(ApiService.class, 4);//指明访问的地址
            service.newSearchCity(location,"fuzzy").enqueue(new NetCallBack<NewSearchCityResponse>() {
                @Override
                public void onSuccess(Call<NewSearchCityResponse> call, Response<NewSearchCityResponse> response) {
                    if(getView() != null){
                        getView().getNewSearchCityResult(response);
                    }
                }

                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getDataFailed();
                    }
                }
            });
        }

接口中

		//搜索城市返回数据  V7
        void getNewSearchCityResult(Response<NewSearchCityResponse> response);

最终如下图所示

OK,现在订阅器都改好了,可以到Activity里面做修改了。

④ 修改Activity

1. 修改MainActivity

打开MainActivity,首先找到

刚才在订阅器里面已经注释掉或者删除了,所以这里没有找到对应方法,这两个你可以删除或者注释,我是删除了。 同样你还需要将

这两个请求在页面上有五件,我建议先注释掉,现在找到报错这一行。

然后会出现一个弹窗,里面会选中6个方法,点击OK就会导入进来,这个时候你的页面就不会再有报错的了。

现在可以在各个方法返回中写入数据了,一个一个来吧。首先是getNewSearchCityResult 在写之前,要做一些简单的代码改动, 打开CodeToStringUtils,增加返回状态码的判断处理,S6和V7是不一样的。所以要增加V7的。

增加的代码如下:

    		//新增V7版本下的状态码判断
            case "204":
                codeInfo = "你查询的地区暂时没有你需要的数据";
                break;
            case "400":
                codeInfo = "请求错误,可能包含错误的请求参数或缺少必选的请求参数";
                break;
            case "401":
                codeInfo = "认证失败,可能使用了错误的KEY、数字签名错误、KEY的类型错误";
                break;
            case "402":
                codeInfo = "超过访问次数或余额不足以支持继续访问服务,你可以充值、升级访问量或等待访问量重置。";
                break;
            case "403":
                codeInfo = "无访问权限,可能是绑定的PackageName、BundleID、域名IP地址不一致,或者是需要额外付费的数据。";
                break;
            case "404":
                codeInfo = "查询的数据或地区不存在。";
                break;
            case "429":
                codeInfo = "超过限定的QPM(每分钟访问次数)";
                break;

你只要放进去就可以了,然后再修改一下Constant,将里面的SUCCESS_CODE改成String类型,值改为“200”,这里还是要吐槽一下,状态码为什么不用Int类型呢?。 改完后如下图所示

在和风 V7 API中,我们并不能通过城市的名称直接拿到相关的数据,需要通过城市的id或者坐标来获取相关的天气预报、逐小时天气、空气质量等等一些其他数据,当然了,百度定位是可以拿到坐标的,完全可以跳过搜索城市这一步,但我还是写了这一步,因为这还涉及到其他页面返回的数据需要查询天气信息的,而其他页面又不是定位得到的,所以还是要查询出城市id的。 这里我定义一个变量用于接收城市id

private String locationId = null;//城市id,用于查询城市数据  V7版本 中 才有

然后看搜索城市的返回处理

	/**
     * 和风天气  V7  API
     * 通过定位到的地址 /  城市切换得到的地址  都需要查询出对应的城市id才行,所以在V7版本中,这是第一步接口
     *
     * @param response
     */
    @Override
    public void getNewSearchCityResult(Response<NewSearchCityResponse> response) {
        refresh.finishRefresh();//关闭刷新
        dismissLoadingDialog();//关闭弹窗
        mLocationClient.stop();//数据返回后关闭定位
        if (response.body().getStatus().equals(Constant.SUCCESS_CODE)) {
            if (response.body().getLocation() != null && response.body().getLocation().size() > 0) {
                tvCity.setText(response.body().getLocation().get(0).getName());//城市
                locationId = response.body().getLocation().get(0).getId();//城市Id

                showLoadingDialog();
                mPresent.nowWeather(locationId);//查询实况天气
                mPresent.dailyWeather(locationId);//查询天气预报
                mPresent.hourlyWeather(locationId);//查询逐小时天气预报
                mPresent.airNowWeather(locationId);//空气质量
                mPresent.lifestyle(locationId);//生活指数
            } else {
                ToastUtils.showShortToast(context, "数据为空");
            }
        } else {
            tvCity.setText("查询城市失败");
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getStatus()));
        }
    }

相信你应该能看懂,在返回中做数据处理,得到城市id之后再去请求其他的数据,虽然请求比较多,但速度比之前的是要快的,这个也是V7相对于S6的优势之一。

还有一个就是V7请求返回值中,所有相关时间都是格林尼治时间。而不是我们常规使用的那种时间格式。所以我特地写了一个方法用于转换,在DateUtils中新增如下方法:

代码如下:

	//根据传入的时间,先转换再截取,得到更新时间  传入  "2020-07-16T09:39+08:00"
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String updateTime(String dateTime) {
        String result = null;

        LocalDateTime date = LocalDateTime.parse(dateTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        String dateString = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        System.out.println("dateString:"+dateString);//到这一步,时间格式已经转换好了
        result = dateString.substring(11);//进一步截取以达到我项目中的需求
        return result;
    }

还有一点要说明一下这种转换方法是要在Android API26及以上才行,所以只要加上一个版本指定注解就可以,

@RequiresApi(api = Build.VERSION_CODES.O)

那么编译器在编译这个方法的时候就会以26的版本去编译,这样你既不用更改build.gradle中的最低API版本也不用担心报错。

现在来看getNowResult方法

	/**
     * 实况天气数据返回  V7
     *
     * @param response
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void getNowResult(Response<NowResponse> response) {
        dismissLoadingDialog();
        if (response.body().getCode().equals(Constant.SUCCESS_CODE)) {//200则成功返回数据
            //根据V7版本的原则,只要是200就一定有数据,我们可以不用做判空处理,但是,为了使程序不ANR,还是要做的,信自己得永生
            NowResponse data = response.body();
            if (data != null) {
                tvTemperature.setText(data.getNow().getTemp());//温度
                if (flag) {
                    ivLocation.setVisibility(View.VISIBLE);//显示定位图标
                } else {
                    ivLocation.setVisibility(View.GONE);//显示定位图标
                }
                tvInfo.setText(data.getNow().getText());//天气状况

                String time = DateUtils.updateTime(data.getUpdateTime());//截去前面的字符,保留后面所有的字符,就剩下 22:00

                tvOldTime.setText("上次更新时间:" + WeatherUtil.showTimeInfo(time) + time);
                tvWindDirection.setText("风向     " + data.getNow().getWindDir());//风向
                tvWindPower.setText("风力     " + data.getNow().getWindScale() + "级");//风力
                wwBig.startRotate();//大风车开始转动
                wwSmall.startRotate();//小风车开始转动
            } else {
                ToastUtils.showShortToast(context, "暂无实况天气数据");
            }
        } else {//其他状态返回提示文字
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode()));
        }
    }

当你写到哪一步发现的报错是我博客中没有提高的,请尽快告诉我,我会及时补上,对自己写的东西负责,也对后面看博客的朋友负责。

现在在adapter包新建一个DailyAdapter.java文件 这是天气预报数据适配器,里面代码如下:

package com.llw.goodweather.adapter;

import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.DailyResponse;
import com.llw.goodweather.utils.WeatherUtil;
import java.util.List;

/**
 * V7 API 天气预报数据列表适配器
 */
public class DailyAdapter extends BaseQuickAdapter<DailyResponse.DailyBean, BaseViewHolder> {
    public DailyAdapter(int layoutResId, @Nullable List<DailyResponse.DailyBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, DailyResponse.DailyBean item) {
        helper.setText(R.id.tv_date, item.getFxDate())//日期
                .setText(R.id.tv_low_and_height, item.getTempMin() + "/" + item.getTempMax() + "℃");//最低温和最高温

        //天气状态图片
        ImageView weatherStateIcon = helper.getView(R.id.iv_weather_state);
        int code = Integer.parseInt(item.getIconDay());//获取天气状态码,根据状态码来显示图标
        WeatherUtil.changeIcon(weatherStateIcon,code);//调用工具类中写好的方法

        helper.addOnClickListener(R.id.item_forecast);//绑定点击事件的id
    }
}

再创建一个HourlyAdapter.java文件,作为逐小时天气预报适配器,代码如下:

package com.llw.goodweather.adapter;

import android.os.Build;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.HourlyResponse;
import com.llw.goodweather.utils.DateUtils;
import com.llw.goodweather.utils.WeatherUtil;
import java.util.List;

/**
 * V7 API 逐小时预报数据列表适配器
 */
public class HourlyAdapter extends BaseQuickAdapter<HourlyResponse.HourlyBean, BaseViewHolder> {
    public HourlyAdapter(int layoutResId, @Nullable List<HourlyResponse.HourlyBean> data) {
        super(layoutResId, data);
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void convert(BaseViewHolder helper, HourlyResponse.HourlyBean item) {
        //首先是对时间格式的处理,因为拿到的时间是  2020-04-28 22:00  要改成   晚上22:00
        //分两步,第一个是字符串的截取,第二个是时间段的判断返回文字描述
        /**
         * V7 API 涉及到时间的,都会返回 2020-07-16T09:39+08:00  这种格式
         * 所以最好写一个通用的返回进行处理 方法已经写好了使用可以了
         */
        String time = DateUtils.updateTime(item.getFxTime());
        helper.setText(R.id.tv_time, WeatherUtil.showTimeInfo(time) + time)//时间
                .setText(R.id.tv_temperature, item.getTemp() + "℃");//温度

        //天气状态图片
        ImageView weatherStateIcon = helper.getView(R.id.iv_weather_state);
        int code = Integer.parseInt(item.getIcon());//获取天气状态码,根据状态码来显示图标
        WeatherUtil.changeIcon(weatherStateIcon, code);
        helper.addOnClickListener(R.id.item_hourly);
    }
}

这里没有问题之后,回到MainActivity

你可以将原来的列表适配器代码注释掉或者删掉。

	//V7 版本
    List<DailyResponse.DailyBean> dailyListV7 = new ArrayList<>();//天气预报数据列表
    DailyAdapter mAdapterDailyV7;//天气预报适配器
    List<HourlyResponse.HourlyBean> hourlyListV7 = new ArrayList<>();//逐小时天气预报数据列表
    HourlyAdapter mAdapterHourlyV7;//逐小时预报适配器

然后再看到initList,先将里面的代码都注释掉或者删掉,然后新增

新增的代码如下:

 		/**   V7 版本   **/
        //天气预报  7天
        mAdapterDailyV7 = new DailyAdapter(R.layout.item_weather_forecast_list, dailyListV7);
        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.setAdapter(mAdapterDailyV7);
        //天气预报列表item点击事件
        mAdapterDailyV7.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                DailyResponse.DailyBean data = dailyListV7.get(position);
                showForecastWindow(data);
            }
        });
        
        //逐小时天气预报  24小时
        mAdapterHourlyV7 = new HourlyAdapter(R.layout.item_weather_hourly_list, hourlyListV7);
        LinearLayoutManager managerHourly = new LinearLayoutManager(context);
        managerHourly.setOrientation(RecyclerView.HORIZONTAL);//设置列表为横向
        rvHourly.setLayoutManager(managerHourly);
        rvHourly.setAdapter(mAdapterHourlyV7);
        //逐小时天气预报列表item点击事件
        mAdapterHourlyV7.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.O)
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                //赋值
                HourlyResponse.HourlyBean data = hourlyListV7.get(position);
                //小时天气详情弹窗
                showHourlyWindow(data);
            }
        });

然后你就会发现showForecastWindowshowHourlyWindow这两个方法报错,是因为传递的数据变了,对应不上,现在来看看这两个方法吧。在这之前,先简单改动一下window_forecast_detail.xml这个弹窗的布局文件

可以删掉了,

然后新增

	<!--云量 新增-->
    <LinearLayout
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <TextView
            android:text="云量"
            android:textColor="@color/black"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
        <TextView
            android:textColor="@color/black"
            android:id="@+id/tv_cloud"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>

再回到MainActivityshowForecastWindow方法处

方法代码如下

	//显示天气预报详情弹窗
    private void showForecastWindow(DailyResponse.DailyBean data) {
        liWindow = new LiWindow(context);
        final View view = LayoutInflater.from(context).inflate(R.layout.window_forecast_detail, null);
        TextView tv_datetime = view.findViewById(R.id.tv_datetime);
        TextView tv_tmp_max = view.findViewById(R.id.tv_tmp_max);//最高温
        TextView tv_tmp_min = view.findViewById(R.id.tv_tmp_min);//最低温
        TextView tv_uv_index = view.findViewById(R.id.tv_uv_index);//紫外线强度
        TextView tv_cond_txt_d = view.findViewById(R.id.tv_cond_txt_d);//白天天气状态
        TextView tv_cond_txt_n = view.findViewById(R.id.tv_cond_txt_n);//晚上天气状态
        TextView tv_wind_deg = view.findViewById(R.id.tv_wind_deg);//风向360角度
        TextView tv_wind_dir = view.findViewById(R.id.tv_wind_dir);//风向
        TextView tv_wind_sc = view.findViewById(R.id.tv_wind_sc);//风力
        TextView tv_wind_spd = view.findViewById(R.id.tv_wind_spd);//风速
        TextView tv_cloud = view.findViewById(R.id.tv_cloud);//云量  V7 新增
        TextView tv_hum = view.findViewById(R.id.tv_hum);//相对湿度
        TextView tv_pres = view.findViewById(R.id.tv_pres);//大气压强
        TextView tv_pcpn = view.findViewById(R.id.tv_pcpn);//降水量
//        TextView tv_pop = view.findViewById(R.id.tv_pop);//降水概率  V7 删除
        TextView tv_vis = view.findViewById(R.id.tv_vis);//能见度

        tv_datetime.setText(data.getFxDate() + "   " + DateUtils.Week(data.getFxDate()));//时间日期
        tv_tmp_max.setText(data.getTempMax() + "℃");
        tv_tmp_min.setText(data.getTempMin() + "℃");
        tv_uv_index.setText(data.getUvIndex());
        tv_cond_txt_d.setText(data.getTextDay());
        tv_cond_txt_n.setText(data.getTextNight());
        tv_wind_deg.setText(data.getWind360Day() + "°");
        tv_wind_dir.setText(data.getWindDirDay());
        tv_wind_sc.setText(data.getWindScaleDay() + "级");
        tv_wind_spd.setText(data.getWindSpeedDay() + "公里/小时");
        tv_cloud.setText(data.getCloud() + "%");//V7 版本中,新增 云量
        tv_hum.setText(data.getHumidity() + "%");
        tv_pres.setText(data.getPressure() + "hPa");
        tv_pcpn.setText(data.getPrecip() + "mm");
//        tv_pop.setText(data.getPop() + "%");//V7 版本中,天气预报中没有降水概率这个值
        tv_vis.setText(data.getVis() + "km");
        liWindow.showCenterPopupWindow(view, SizeUtils.dp2px(context, 300), SizeUtils.dp2px(context, 500), true);

    }

再看showHourlyWindow

	//显示小时详情天气信息弹窗
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void showHourlyWindow(HourlyResponse.HourlyBean data) {
        liWindow = new LiWindow(context);
        final View view = LayoutInflater.from(context).inflate(R.layout.window_hourly_detail, null);
        TextView tv_time = view.findViewById(R.id.tv_time);//时间
        TextView tv_tem = view.findViewById(R.id.tv_tem);//温度
        TextView tv_cond_txt = view.findViewById(R.id.tv_cond_txt);//天气状态描述
        TextView tv_wind_deg = view.findViewById(R.id.tv_wind_deg);//风向360角度
        TextView tv_wind_dir = view.findViewById(R.id.tv_wind_dir);//风向
        TextView tv_wind_sc = view.findViewById(R.id.tv_wind_sc);//风力
        TextView tv_wind_spd = view.findViewById(R.id.tv_wind_spd);//风速
        TextView tv_hum = view.findViewById(R.id.tv_hum);//相对湿度
        TextView tv_pres = view.findViewById(R.id.tv_pres);//大气压强
        TextView tv_pop = view.findViewById(R.id.tv_pop);//降水概率
        TextView tv_dew = view.findViewById(R.id.tv_dew);//露点温度
        TextView tv_cloud = view.findViewById(R.id.tv_cloud);//云量
        
        String time = DateUtils.updateTime(data.getFxTime());
        tv_time.setText(WeatherUtil.showTimeInfo(time) + time);
        tv_tem.setText(data.getTemp() + "℃");
        tv_cond_txt.setText(data.getText());
        tv_wind_deg.setText(data.getWind360() + "°");
        tv_wind_dir.setText(data.getWindDir());
        tv_wind_sc.setText(data.getWindScale() + "级");
        tv_wind_spd.setText(data.getWindSpeed() + "公里/小时");
        tv_hum.setText(data.getHumidity() + "%");
        tv_pres.setText(data.getPressure() + "hPa");
        tv_pop.setText(data.getPop() + "%");
        tv_dew.setText(data.getDew() + "℃");
        tv_cloud.setText(data.getCloud() + "%");
        liWindow.showCenterPopupWindow(view, SizeUtils.dp2px(context, 300), SizeUtils.dp2px(context, 400), true);
    }

里面只有些许值和你之前的不一样,你直接替换就可以了。 然后再来看这个getDailyResult方法返回

	/**
     * 天气预报数据返回  V7
     *
     * @param response
     */
    @Override
    public void getDailyResult(Response<DailyResponse> response) {
        if (response.body().getCode().equals(Constant.SUCCESS_CODE)) {
            List<DailyResponse.DailyBean> data = response.body().getDaily();
            if (data != null && data.size() > 0) {//判空处理
                tvLowHeight.setText(data.get(0).getTempMin() + " / " + data.get(0).getTempMax() + "℃");
                dailyListV7.clear();//添加数据之前先清除
                dailyListV7.addAll(data);//添加数据
                mAdapterDailyV7.notifyDataSetChanged();//刷新列表
            } else {
                ToastUtils.showShortToast(context, "天气预报数据为空");
            }
        } else {//异常状态码返回
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode()));
        }
    }

列表赋值,然后刷新适配器进行数据渲染。 再看getHourlyResult方法返回

	/**
     * 逐小时天气数据返回  V7
     * @param response
     */
    @Override
    public void getHourlyResult(Response<HourlyResponse> response) {
        if(response.body().getCode().equals(Constant.SUCCESS_CODE)){
            List<HourlyResponse.HourlyBean> data = response.body().getHourly();
            if(data != null && data.size()> 0){
                hourlyListV7.clear();
                hourlyListV7.addAll(data);
                mAdapterHourlyV7.notifyDataSetChanged();
            }else {
                ToastUtils.showShortToast(context, "逐小时预报数据为空");
            }
        }else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode()));
        }
    }

内容差不多的,只不过数据不同 接下来就是空气质量和生活数据返回的处理了

先看getAirNowResult方法返回

	/**
     * 空气质量返回  V7
     * @param response
     */
    @Override
    public void getAirNowResult(Response<AirNowResponse> response) {
        if(response.body().getCode().equals(Constant.SUCCESS_CODE)){
            AirNowResponse.NowBean data = response.body().getNow();
            if(response.body().getNow() !=null){
                rpbAqi.setMaxProgress(300);//最大进度,用于计算
                rpbAqi.setMinText("0");//设置显示最小值
                rpbAqi.setMinTextSize(32f);
                rpbAqi.setMaxText("300");//设置显示最大值
                rpbAqi.setMaxTextSize(32f);
                rpbAqi.setProgress(Float.valueOf(data.getAqi()));//当前进度
                rpbAqi.setArcBgColor(getResources().getColor(R.color.arc_bg_color));//圆弧的颜色
                rpbAqi.setProgressColor(getResources().getColor(R.color.arc_progress_color));//进度圆弧的颜色
                rpbAqi.setFirstText(data.getCategory());//空气质量描述 取值范围:优,良,轻度污染,中度污染,重度污染,严重污染
                rpbAqi.setFirstTextSize(44f);//第一行文本的字体大小
                rpbAqi.setSecondText(data.getAqi());//空气质量值
                rpbAqi.setSecondTextSize(64f);//第二行文本的字体大小
                rpbAqi.setMinText("0");
                rpbAqi.setMinTextColor(getResources().getColor(R.color.arc_progress_color));

                tvPm10.setText(data.getPm10());//PM10
                tvPm25.setText(data.getPm10());//PM2.5
                tvNo2.setText(data.getNo2());//二氧化氮
                tvSo2.setText(data.getSo2());//二氧化硫
                tvO3.setText(data.getO3());//臭氧
                tvCo.setText(data.getCo());//一氧化碳
            }else {
                ToastUtils.showShortToast(context,"空气质量数据为空");
            }
        }else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode()));
        }
    }

最大值从500变为300了。

生活数据getLifestyleResult方法返回

	/**
     * 生活数据返回 V7
     * @param response
     */
    @Override
    public void getLifestyleResult(Response<LifestyleResponse> response) {
        if(response.body().getCode().equals(Constant.SUCCESS_CODE)){
            List<LifestyleResponse.DailyBean> data = response.body().getDaily();
            for (int i = 0; i < data.size(); i++) {
                switch (data.get(i).getType()) {
                    case "5":
                        tvUv.setText("紫外线:" + data.get(i).getText());
                        break;
                    case "8":
                        tvComf.setText("舒适度:" + data.get(i).getText());
                        break;
                    case "3":
                        tvDrsg.setText("穿衣指数:" + data.get(i).getText());
                        break;
                    case "9":
                        tvFlu.setText("感冒指数:" + data.get(i).getText());
                        break;
                    case "1":
                        tvSport.setText("运动指数:" + data.get(i).getText());
                        break;
                    case "6":
                        tvTrav.setText("旅游指数:" + data.get(i).getText());
                        break;
                    case "2":
                        tvCw.setText("洗车指数:" + data.get(i).getText());
                        break;
                    case "10":
                        tvAir.setText("空气指数:" + data.get(i).getText());
                        break;
                }
            }
        }else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getCode()));
        }
    }

注意里面的变化,现在是根据Type的值获取对应的详细数据了。 现在对这个返回的数据做了处理,下面就是要在相应的地方添加请求了,不请求就肯定没有数据返回的。 第一个地方有两处改动,定位之后和下拉刷新的时候

第二个地方是切换城市之后

第三个是在onResume

第四个是在接收都相应的事件之后

MainActiivty的改动已经完成了,接下来改动SearchCityActivity

2. 修改SearchCityActivity

先修改SearchCityAdapter,因为数据源变了

package com.llw.goodweather.adapter;

import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.NewSearchCityResponse;
import java.util.List;

/**
 * 搜索城市结果列表适配器  V7
 */
public class SearchCityAdapter extends BaseQuickAdapter<NewSearchCityResponse.LocationBean, BaseViewHolder> {
    public SearchCityAdapter(int layoutResId, @Nullable List<NewSearchCityResponse.LocationBean> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, NewSearchCityResponse.LocationBean item) {
        helper.setText(R.id.tv_city_name, item.getName());
        helper.addOnClickListener(R.id.tv_city_name);//绑定点击事件

    }
}

这里增加了新的数据实体,可以把原来的删掉或者注释掉

再看返回方法,删除原来的getSearchCityResult返回方法。 新增如下:

	/**
     * 搜索城市返回数据  V7
     *
     * @param response
     */
    @Override
    public void getNewSearchCityResult(Response<NewSearchCityResponse> response) {
        dismissLoadingDialog();
        if (response.body().getStatus().equals(Constant.SUCCESS_CODE)) {
            mList.clear();
            mList.addAll(response.body().getLocation());
            mAdapter.notifyDataSetChanged();
            runLayoutAnimation(rv);
        } else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getStatus()));
        }
    }

你的代码中这行代码

mPresent.searchCity(context, location);

肯定也会报错,将其替换为

mPresent.newSearchCity(location);//搜索城市  V7

到这里搜索页面的布局基本已经改完了。 如果你还有什么报错的地方和我说一下,因为这次的代码改动量很大,我也是改完再写的,所以有的地方可能跳过了过程。

⑤ 更换V7天气图标

最后我们再更换一下新版API的天气图标吧

我用的是这个比较立体的,这是图标的下载地址,当然了,你要是懒得改,就直接在我的GitHub上复制过来就可以了。 改完图标的运行效果如下:

看起来还是不错吧。