Android 天气APP(十四)修复UI显示异常、优化业务代码逻辑、增加详情天气显示

简介: Android 天气APP(十四)修复UI显示异常、优化业务代码逻辑、增加详情天气显示

完成此篇文章之后的运行效果图

20200528110536875.gif


前言


在上一篇文章中增加了自定义背景的功能的同时也遗留了一些问题,为阅读者带来的不便,敬请谅解,在这一篇中将会优化这些问题,同时优化业务逻辑代码,做到用最少的代码量办最多的事情,同时对UI的用户体验进一步提升,增加天气详情数据的显示。


正文


首先是修复之前问题吧,这个问题我本身是知道的,不过因为工作时间的原因,近期就没有来得及改这个问题,但我又不想在原来的第十三篇文章中进行修正,因为有问题很正常,正视这个问题并解决就好了,这个问题说起来也比较的简单,就是Actvity的生命周期没有处理好造成了数据异常提示。


首先在MainActivity.java中的

private boolean flagOther = false;//跳转其他页面时才为true


然后在Constant.java中增加一个Key

public final static String FLAG_OTHER_RETURN="flag_other_return";//跳转页面的标识


回到MainActivity.java中,Ctrl + F 搜索当前页面,在搜索输入框输入changeBg.setOnClickListener,改动如下图所示。

20210207151324646.png


改完了这里,再搜索onResume,改动如下图所示:

20200516103014159.png

这个代码逻辑是这样的

在Activity的生命周期中,一个Activity的执行过程是onCreate→onStart→onResume,如果这个时候你跳转到另一个页面,那么当前页面将执行onPause→onStop,而新页面将会执行onCreate→onStart→onResume,如果这个时候我们通过返回键返回到之前的页面,新页面会执行onPause→onStop,之前的页面会执行onRestart→onStart→onResume。通过这个操作你是不是明白我为什么要在onResume方法里面做逻辑处理了呢。首先一进来这个页面就会执行onResume方法,这个时候我取缓存的值来判断,但是缓存中没有值的话就是默认的false,而false则不会执行里面的方法,但当我跳转到切换背景页面时,这个缓存中已经赋值为true,这时不管我有没有设置背景模式,缓存中都会有值,而另一个页面返回到之前页面也会执行onResume方法,这时,就为true了,所以就会执行里面的业务逻辑代码,不知道你理解了没有。

问题修复之后,优化提示文本,在app的utils包下创建一个CodeToStringUtils工具类


20200516141915226.png


代码如下:

package com.llw.goodweather.utils;
public class CodeToStringUtils {
    public static String WeatherCode(String code){
        String codeInfo = null;
        switch (code){
            case "ok":
                codeInfo = "正常";
                break;
            case "invalid key":
                codeInfo = "无效的key";
                break;
            case "invalid key type":
                codeInfo = "你输入的key不适用于当前获取数据的方式,即SDK的KEY不能用于Web API或通过接口直接访问,反之亦然。";
                break;
            case "invalid param":
                codeInfo = "无效的参数,请检查你传递的参数是否正确、完整";
                break;
            case "bad bind":
                codeInfo = "错误的绑定,例如绑定的package name、bundle id或IP地址不一致的时候";
                break;
            case "no data for this location":
                codeInfo = "该城市/地区没有你所请求的数据";
                break;
            case "no more requests":
                codeInfo = "超过访问次数,需要等到当月最后一天24点(免费用户为当天24点)后进行访问次数的重置或升级你的访问量";
                break;
            case "no balance":
                codeInfo = "没有余额,你的按量计费产品由于余额不足或欠费而不能访问,请尽快充值";
                break;
            case "too fast":
                codeInfo = "超过限定的QPM";
                break;
            case "dead":
                codeInfo = "无响应或超时";
                break;
            case "unknown location":
                codeInfo = "没有你查询的这个地区,或者地区名称错误";
                break;
            case "permission denied":
                codeInfo = "无访问权限,你没有购买你所访问的这部分服务";
                break;
            case "sign error":
                codeInfo = "签名错误";
                break;
        }
        return codeInfo;
    }
}


这里就是根据和风API的返回码匹配上中文提示,因为用户那里知道你的英文是什么意思呢?所以这样会比较好一些,接下来就是使用这个了。


20200516142435578.png


这里我就是举个例子,有好几个方法,你可以全部都改了。


优化代码


优化代码,无非就是精简,怎么精简呢,首先从接口上来看怎么精简。我们现在一共是用了两个接口,一个是和风天气的、一个是必应每日一图的。而和风天气的接口下面有五个子接口,其中前四个是一个分支接口下来的,也就是weather,后一个是在air下的空气质量,这一个空气质量,免费的就只有当前的空气质量,但是前一个weather接口的返回数据是我们根据不同的类型去改变url地址得到的数据,既然都在weather下,是否能够四合一呢?写一个就搞定呢?这样代码量会不会少很多呢?

带着这些思考去实践一下。


实践之前,我先给生活指数加上一个紫外线的数据返回显示,首先修改activity_main.xml文件


20200516143406589.png


在舒适度的上方加一个显示紫外线的,深圳的紫外线太强了,讲真的。然后修改MainActivity.xml

20200516143602298.png

20200516144548766.png


这里我把原来的if判断改为了switch这样看起来更清晰一些,不容易出错,但是用switch要记得break;


          switch (data.get(i).getType()){
                        case "uv":
                            tvUv.setText("紫外线:" + data.get(i).getTxt());
                            break;
                        case "comf":
                            tvComf.setText("舒适度:" + data.get(i).getTxt());
                            break;
                        case "drsg":
                            tvDrsg.setText("穿衣指数:" + data.get(i).getTxt());
                            break;
                        case "flu":
                            tvFlu.setText("感冒指数:" + data.get(i).getTxt());
                            break;
                        case "sport":
                            tvSport.setText("运动指数:" + data.get(i).getTxt());
                            break;
                        case "trav":
                            tvTrav.setText("旅游指数:" + data.get(i).getTxt());
                            break;
                        case "cw":
                            tvCw.setText("洗车指数:" + data.get(i).getTxt());
                            break;
                        case "air":
                            tvAir.setText("空气指数:" + data.get(i).getTxt());
                            break;
                    }


现在去合并接口吧。


合并之前需要一个访问地址。


https://free-api.heweather.net/s6/weather?key=3086e91d66c04ce588a7f538f917c7f4&location=深圳


拿到返回值,生成实体bean


20200516150546891.png


代码如下:

package com.llw.goodweather.bean;
import java.util.List;
public class WeatherResponse {
    private List<HeWeather6Bean> HeWeather6;
    public List<HeWeather6Bean> getHeWeather6() {
        return HeWeather6;
    }
    public void setHeWeather6(List<HeWeather6Bean> HeWeather6) {
        this.HeWeather6 = HeWeather6;
    }
    public static class HeWeather6Bean {
        /**
         * basic : {"cid":"CN101280601","location":"深圳","parent_city":"深圳","admin_area":"广东","cnty":"中国","lat":"22.54700089","lon":"114.08594513","tz":"+8.00"}
         * update : {"loc":"2020-05-16 10:03","utc":"2020-05-16 02:03"}
         * status : ok
         * now : {"cloud":"10","cond_code":"100","cond_txt":"晴","fl":"33","hum":"74","pcpn":"0.0","pres":"1001","tmp":"29","vis":"16","wind_deg":"227","wind_dir":"西南风","wind_sc":"1","wind_spd":"2"}
         * daily_forecast : [{"cond_code_d":"101","cond_code_n":"104","cond_txt_d":"多云","cond_txt_n":"阴","date":"2020-05-16","hum":"83","mr":"01:57","ms":"13:36","pcpn":"0.0","pop":"4","pres":"998","sr":"05:42","ss":"18:57","tmp_max":"34","tmp_min":"24","uv_index":"9","vis":"25","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"6"},{"cond_code_d":"302","cond_code_n":"306","cond_txt_d":"雷阵雨","cond_txt_n":"中雨","date":"2020-05-17","hum":"83","mr":"02:31","ms":"14:26","pcpn":"0.0","pop":"25","pres":"995","sr":"05:42","ss":"18:58","tmp_max":"33","tmp_min":"25","uv_index":"1","vis":"15","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"11"},{"cond_code_d":"306","cond_code_n":"307","cond_txt_d":"中雨","cond_txt_n":"大雨","date":"2020-05-18","hum":"88","mr":"03:04","ms":"15:15","pcpn":"5.1","pop":"80","pres":"996","sr":"05:41","ss":"18:58","tmp_max":"28","tmp_min":"24","uv_index":"2","vis":"22","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"6"},{"cond_code_d":"306","cond_code_n":"300","cond_txt_d":"中雨","cond_txt_n":"阵雨","date":"2020-05-19","hum":"78","mr":"03:37","ms":"16:04","pcpn":"6.1","pop":"68","pres":"997","sr":"05:41","ss":"18:59","tmp_max":"30","tmp_min":"26","uv_index":"0","vis":"22","wind_deg":"234","wind_dir":"西南风","wind_sc":"3-4","wind_spd":"15"},{"cond_code_d":"300","cond_code_n":"316","cond_txt_d":"阵雨","cond_txt_n":"大到暴雨","date":"2020-05-20","hum":"81","mr":"04:09","ms":"16:53","pcpn":"0.0","pop":"25","pres":"997","sr":"05:41","ss":"18:59","tmp_max":"31","tmp_min":"25","uv_index":"10","vis":"22","wind_deg":"234","wind_dir":"西南风","wind_sc":"3-4","wind_spd":"20"},{"cond_code_d":"316","cond_code_n":"316","cond_txt_d":"大到暴雨","cond_txt_n":"大到暴雨","date":"2020-05-21","hum":"81","mr":"04:42","ms":"17:45","pcpn":"5.1","pop":"80","pres":"994","sr":"05:40","ss":"19:00","tmp_max":"30","tmp_min":"25","uv_index":"3","vis":"13","wind_deg":"226","wind_dir":"西南风","wind_sc":"3-4","wind_spd":"20"},{"cond_code_d":"306","cond_code_n":"310","cond_txt_d":"中雨","cond_txt_n":"暴雨","date":"2020-05-22","hum":"86","mr":"05:19","ms":"18:37","pcpn":"6.1","pop":"68","pres":"996","sr":"05:40","ss":"19:00","tmp_max":"31","tmp_min":"27","uv_index":"5","vis":"8","wind_deg":"244","wind_dir":"西南风","wind_sc":"3-4","wind_spd":"23"}]
         * hourly : [{"cloud":"11","cond_code":"101","cond_txt":"多云","dew":"22","hum":"73","pop":"7","pres":"998","time":"2020-05-16 13:00","tmp":"33","wind_deg":"174","wind_dir":"南风","wind_sc":"1-2","wind_spd":"5"},{"cloud":"9","cond_code":"101","cond_txt":"多云","dew":"22","hum":"73","pop":"7","pres":"999","time":"2020-05-16 16:00","tmp":"33","wind_deg":"188","wind_dir":"南风","wind_sc":"1-2","wind_spd":"2"},{"cloud":"19","cond_code":"101","cond_txt":"多云","dew":"24","hum":"81","pop":"0","pres":"997","time":"2020-05-16 19:00","tmp":"29","wind_deg":"170","wind_dir":"南风","wind_sc":"1-2","wind_spd":"11"},{"cloud":"74","cond_code":"101","cond_txt":"多云","dew":"25","hum":"85","pop":"0","pres":"998","time":"2020-05-16 22:00","tmp":"25","wind_deg":"181","wind_dir":"南风","wind_sc":"1-2","wind_spd":"3"},{"cloud":"68","cond_code":"104","cond_txt":"阴","dew":"24","hum":"85","pop":"0","pres":"999","time":"2020-05-17 01:00","tmp":"25","wind_deg":"187","wind_dir":"南风","wind_sc":"1-2","wind_spd":"9"},{"cloud":"70","cond_code":"104","cond_txt":"阴","dew":"25","hum":"84","pop":"0","pres":"998","time":"2020-05-17 04:00","tmp":"24","wind_deg":"182","wind_dir":"南风","wind_sc":"1-2","wind_spd":"11"},{"cloud":"65","cond_code":"104","cond_txt":"阴","dew":"26","hum":"84","pop":"43","pres":"996","time":"2020-05-17 07:00","tmp":"26","wind_deg":"188","wind_dir":"南风","wind_sc":"1-2","wind_spd":"1"},{"cloud":"52","cond_code":"104","cond_txt":"阴","dew":"23","hum":"77","pop":"46","pres":"995","time":"2020-05-17 10:00","tmp":"31","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"8"}]
         * lifestyle : [{"type":"comf","brf":"较不舒适","txt":"白天天气多云,并且空气湿度偏大,在这种天气条件下,您会感到有些闷热,不很舒适。"},{"type":"drsg","brf":"炎热","txt":"天气炎热,建议着短衫、短裙、短裤、薄型T恤衫等清凉夏季服装。"},{"type":"flu","brf":"少发","txt":"各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。"},{"type":"sport","brf":"较不宜","txt":"天气较好,无雨水困扰,但考虑气温很高,请注意适当减少运动时间并降低运动强度,运动后及时补充水分。"},{"type":"trav","brf":"较适宜","txt":"天气较好,温度较高,天气较热,但有微风相伴,还是比较适宜旅游的,不过外出时要注意防暑防晒哦!"},{"type":"uv","brf":"强","txt":"紫外线辐射强,建议涂擦SPF20左右、PA++的防晒护肤品。避免在10点至14点暴露于日光下。"},{"type":"cw","brf":"较适宜","txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"},{"type":"air","brf":"中","txt":"气象条件对空气污染物稀释、扩散和清除无明显影响。"}]
         */
        private BasicBean basic;
        private UpdateBean update;
        private String status;
        private NowBean now;
        private List<DailyForecastBean> daily_forecast;
        private List<HourlyBean> hourly;
        private List<LifestyleBean> lifestyle;
        public BasicBean getBasic() {
            return basic;
        }
        public void setBasic(BasicBean basic) {
            this.basic = basic;
        }
        public UpdateBean getUpdate() {
            return update;
        }
        public void setUpdate(UpdateBean update) {
            this.update = update;
        }
        public String getStatus() {
            return status;
        }
        public void setStatus(String status) {
            this.status = status;
        }
        public NowBean getNow() {
            return now;
        }
        public void setNow(NowBean now) {
            this.now = now;
        }
        public List<DailyForecastBean> getDaily_forecast() {
            return daily_forecast;
        }
        public void setDaily_forecast(List<DailyForecastBean> daily_forecast) {
            this.daily_forecast = daily_forecast;
        }
        public List<HourlyBean> getHourly() {
            return hourly;
        }
        public void setHourly(List<HourlyBean> hourly) {
            this.hourly = hourly;
        }
        public List<LifestyleBean> getLifestyle() {
            return lifestyle;
        }
        public void setLifestyle(List<LifestyleBean> lifestyle) {
            this.lifestyle = lifestyle;
        }
        public static class BasicBean {
            /**
             * cid : CN101280601
             * location : 深圳
             * parent_city : 深圳
             * admin_area : 广东
             * cnty : 中国
             * lat : 22.54700089
             * lon : 114.08594513
             * tz : +8.00
             */
            private String cid;
            private String location;
            private String parent_city;
            private String admin_area;
            private String cnty;
            private String lat;
            private String lon;
            private String tz;
            public String getCid() {
                return cid;
            }
            public void setCid(String cid) {
                this.cid = cid;
            }
            public String getLocation() {
                return location;
            }
            public void setLocation(String location) {
                this.location = location;
            }
            public String getParent_city() {
                return parent_city;
            }
            public void setParent_city(String parent_city) {
                this.parent_city = parent_city;
            }
            public String getAdmin_area() {
                return admin_area;
            }
            public void setAdmin_area(String admin_area) {
                this.admin_area = admin_area;
            }
            public String getCnty() {
                return cnty;
            }
            public void setCnty(String cnty) {
                this.cnty = cnty;
            }
            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 getTz() {
                return tz;
            }
            public void setTz(String tz) {
                this.tz = tz;
            }
        }
        public static class UpdateBean {
            /**
             * loc : 2020-05-16 10:03
             * utc : 2020-05-16 02:03
             */
            private String loc;
            private String utc;
            public String getLoc() {
                return loc;
            }
            public void setLoc(String loc) {
                this.loc = loc;
            }
            public String getUtc() {
                return utc;
            }
            public void setUtc(String utc) {
                this.utc = utc;
            }
        }
        public static class NowBean {
            /**
             * cloud : 10
             * cond_code : 100
             * cond_txt : 晴
             * fl : 33
             * hum : 74
             * pcpn : 0.0
             * pres : 1001
             * tmp : 29
             * vis : 16
             * wind_deg : 227
             * wind_dir : 西南风
             * wind_sc : 1
             * wind_spd : 2
             */
            private String cloud;
            private String cond_code;
            private String cond_txt;
            private String fl;
            private String hum;
            private String pcpn;
            private String pres;
            private String tmp;
            private String vis;
            private String wind_deg;
            private String wind_dir;
            private String wind_sc;
            private String wind_spd;
            public String getCloud() {
                return cloud;
            }
            public void setCloud(String cloud) {
                this.cloud = cloud;
            }
            public String getCond_code() {
                return cond_code;
            }
            public void setCond_code(String cond_code) {
                this.cond_code = cond_code;
            }
            public String getCond_txt() {
                return cond_txt;
            }
            public void setCond_txt(String cond_txt) {
                this.cond_txt = cond_txt;
            }
            public String getFl() {
                return fl;
            }
            public void setFl(String fl) {
                this.fl = fl;
            }
            public String getHum() {
                return hum;
            }
            public void setHum(String hum) {
                this.hum = hum;
            }
            public String getPcpn() {
                return pcpn;
            }
            public void setPcpn(String pcpn) {
                this.pcpn = pcpn;
            }
            public String getPres() {
                return pres;
            }
            public void setPres(String pres) {
                this.pres = pres;
            }
            public String getTmp() {
                return tmp;
            }
            public void setTmp(String tmp) {
                this.tmp = tmp;
            }
            public String getVis() {
                return vis;
            }
            public void setVis(String vis) {
                this.vis = vis;
            }
            public String getWind_deg() {
                return wind_deg;
            }
            public void setWind_deg(String wind_deg) {
                this.wind_deg = wind_deg;
            }
            public String getWind_dir() {
                return wind_dir;
            }
            public void setWind_dir(String wind_dir) {
                this.wind_dir = wind_dir;
            }
            public String getWind_sc() {
                return wind_sc;
            }
            public void setWind_sc(String wind_sc) {
                this.wind_sc = wind_sc;
            }
            public String getWind_spd() {
                return wind_spd;
            }
            public void setWind_spd(String wind_spd) {
                this.wind_spd = wind_spd;
            }
        }
        public static class DailyForecastBean {
            /**
             * cond_code_d : 101
             * cond_code_n : 104
             * cond_txt_d : 多云
             * cond_txt_n : 阴
             * date : 2020-05-16
             * hum : 83
             * mr : 01:57
             * ms : 13:36
             * pcpn : 0.0
             * pop : 4
             * pres : 998
             * sr : 05:42
             * ss : 18:57
             * tmp_max : 34
             * tmp_min : 24
             * uv_index : 9
             * vis : 25
             * wind_deg : -1
             * wind_dir : 无持续风向
             * wind_sc : 1-2
             * wind_spd : 6
             */
            private String cond_code_d;
            private String cond_code_n;
            private String cond_txt_d;
            private String cond_txt_n;
            private String date;
            private String hum;
            private String mr;
            private String ms;
            private String pcpn;
            private String pop;
            private String pres;
            private String sr;
            private String ss;
            private String tmp_max;
            private String tmp_min;
            private String uv_index;
            private String vis;
            private String wind_deg;
            private String wind_dir;
            private String wind_sc;
            private String wind_spd;
            public String getCond_code_d() {
                return cond_code_d;
            }
            public void setCond_code_d(String cond_code_d) {
                this.cond_code_d = cond_code_d;
            }
            public String getCond_code_n() {
                return cond_code_n;
            }
            public void setCond_code_n(String cond_code_n) {
                this.cond_code_n = cond_code_n;
            }
            public String getCond_txt_d() {
                return cond_txt_d;
            }
            public void setCond_txt_d(String cond_txt_d) {
                this.cond_txt_d = cond_txt_d;
            }
            public String getCond_txt_n() {
                return cond_txt_n;
            }
            public void setCond_txt_n(String cond_txt_n) {
                this.cond_txt_n = cond_txt_n;
            }
            public String getDate() {
                return date;
            }
            public void setDate(String date) {
                this.date = date;
            }
            public String getHum() {
                return hum;
            }
            public void setHum(String hum) {
                this.hum = hum;
            }
            public String getMr() {
                return mr;
            }
            public void setMr(String mr) {
                this.mr = mr;
            }
            public String getMs() {
                return ms;
            }
            public void setMs(String ms) {
                this.ms = ms;
            }
            public String getPcpn() {
                return pcpn;
            }
            public void setPcpn(String pcpn) {
                this.pcpn = pcpn;
            }
            public String getPop() {
                return pop;
            }
            public void setPop(String pop) {
                this.pop = pop;
            }
            public String getPres() {
                return pres;
            }
            public void setPres(String pres) {
                this.pres = pres;
            }
            public String getSr() {
                return sr;
            }
            public void setSr(String sr) {
                this.sr = sr;
            }
            public String getSs() {
                return ss;
            }
            public void setSs(String ss) {
                this.ss = ss;
            }
            public String getTmp_max() {
                return tmp_max;
            }
            public void setTmp_max(String tmp_max) {
                this.tmp_max = tmp_max;
            }
            public String getTmp_min() {
                return tmp_min;
            }
            public void setTmp_min(String tmp_min) {
                this.tmp_min = tmp_min;
            }
            public String getUv_index() {
                return uv_index;
            }
            public void setUv_index(String uv_index) {
                this.uv_index = uv_index;
            }
            public String getVis() {
                return vis;
            }
            public void setVis(String vis) {
                this.vis = vis;
            }
            public String getWind_deg() {
                return wind_deg;
            }
            public void setWind_deg(String wind_deg) {
                this.wind_deg = wind_deg;
            }
            public String getWind_dir() {
                return wind_dir;
            }
            public void setWind_dir(String wind_dir) {
                this.wind_dir = wind_dir;
            }
            public String getWind_sc() {
                return wind_sc;
            }
            public void setWind_sc(String wind_sc) {
                this.wind_sc = wind_sc;
            }
            public String getWind_spd() {
                return wind_spd;
            }
            public void setWind_spd(String wind_spd) {
                this.wind_spd = wind_spd;
            }
        }
        public static class HourlyBean {
            /**
             * cloud : 11
             * cond_code : 101
             * cond_txt : 多云
             * dew : 22
             * hum : 73
             * pop : 7
             * pres : 998
             * time : 2020-05-16 13:00
             * tmp : 33
             * wind_deg : 174
             * wind_dir : 南风
             * wind_sc : 1-2
             * wind_spd : 5
             */
            private String cloud;
            private String cond_code;
            private String cond_txt;
            private String dew;
            private String hum;
            private String pop;
            private String pres;
            private String time;
            private String tmp;
            private String wind_deg;
            private String wind_dir;
            private String wind_sc;
            private String wind_spd;
            public String getCloud() {
                return cloud;
            }
            public void setCloud(String cloud) {
                this.cloud = cloud;
            }
            public String getCond_code() {
                return cond_code;
            }
            public void setCond_code(String cond_code) {
                this.cond_code = cond_code;
            }
            public String getCond_txt() {
                return cond_txt;
            }
            public void setCond_txt(String cond_txt) {
                this.cond_txt = cond_txt;
            }
            public String getDew() {
                return dew;
            }
            public void setDew(String dew) {
                this.dew = dew;
            }
            public String getHum() {
                return hum;
            }
            public void setHum(String hum) {
                this.hum = hum;
            }
            public String getPop() {
                return pop;
            }
            public void setPop(String pop) {
                this.pop = pop;
            }
            public String getPres() {
                return pres;
            }
            public void setPres(String pres) {
                this.pres = pres;
            }
            public String getTime() {
                return time;
            }
            public void setTime(String time) {
                this.time = time;
            }
            public String getTmp() {
                return tmp;
            }
            public void setTmp(String tmp) {
                this.tmp = tmp;
            }
            public String getWind_deg() {
                return wind_deg;
            }
            public void setWind_deg(String wind_deg) {
                this.wind_deg = wind_deg;
            }
            public String getWind_dir() {
                return wind_dir;
            }
            public void setWind_dir(String wind_dir) {
                this.wind_dir = wind_dir;
            }
            public String getWind_sc() {
                return wind_sc;
            }
            public void setWind_sc(String wind_sc) {
                this.wind_sc = wind_sc;
            }
            public String getWind_spd() {
                return wind_spd;
            }
            public void setWind_spd(String wind_spd) {
                this.wind_spd = wind_spd;
            }
        }
        public static class LifestyleBean {
            /**
             * type : comf
             * brf : 较不舒适
             * txt : 白天天气多云,并且空气湿度偏大,在这种天气条件下,您会感到有些闷热,不很舒适。
             */
            private String type;
            private String brf;
            private String txt;
            public String getType() {
                return type;
            }
            public void setType(String type) {
                this.type = type;
            }
            public String getBrf() {
                return brf;
            }
            public void setBrf(String brf) {
                this.brf = brf;
            }
            public String getTxt() {
                return txt;
            }
            public void setTxt(String txt) {
                this.txt = txt;
            }
        }
    }
}


在ApiService中增加

20200516150758673.png


  /**
     * 获取所有天气数据,在返回值中再做处理
     * @param location
     * @return
     */
    @GET("/s6/weather?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<WeatherResponse> weatherData(@Query("location") String location);


在WeatherContract中增加订阅20200516160325675.png

20200516160425325.png

    /**
         * 天气所有数据
         * @param context
         * @param location
         */
        public void weatherData(final Context context,String location){
            ApiService service = ServiceGenerator.createService(ApiService.class,0);
            service.weatherData(location).enqueue(new NetCallBack<WeatherResponse>() {
                @Override
                public void onSuccess(Call<WeatherResponse> call, Response<WeatherResponse> response) {
                    if(getView() != null){
                        getView().getWeatherDataResult(response);
                    }
                }
                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getWeatherDataFailed();
                    }
                }
            });
        }
    //查询天气所有数据
        void getWeatherDataResult(Response<WeatherResponse> response);
        //天气数据获取错误返回
        void getWeatherDataFailed();


进入MainActivity.java中


2020051615175113.png


  /**
     * 所有天气数据返回
     * @param response
     */
    @Override
    public void getWeatherDataResult(Response<WeatherResponse> response) {
        dismissLoadingDialog();//关闭弹窗
        if (("ok").equals(response.body().getHeWeather6().get(0).getStatus())) {
        }else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getHeWeather6().get(0).getStatus()));
        }
    }


首先改动适配器


七天天气预报适配器WeatherForecastAdapter.java

20200516155133868.png


逐小时天气预报适配器WeatherHourlyAdapter.java

20200516155249731.png


然后回到MainActivity.java

20200516155436490.png


红框中为新增的,然后之前的注释掉,当所有的改动都完成之后,再删除掉注释的没有用的代码、

2020051615560769.png


红框中的就是你要改动的

然后修改切换城市之后的方法请求

20200516155759929.png


定位后

2020051615595314.png


下拉刷新之后

20200516160018446.png


onResume方法中

2020051616174940.png

20200516160114672.png


返回值里面的业务逻辑处理代码先注释掉,最后修改getWeatherDataResult。

修改代码如下:


/**
     * 所有天气数据返回
     * @param response
     */
    @Override
    public void getWeatherDataResult(Response<WeatherResponse> response) {
        refresh.finishRefresh();//关闭刷新
        dismissLoadingDialog();//关闭弹窗
        if (mLocationClient != null) {
            mLocationClient.stop();//数据返回后关闭定位
        }
        if (("ok").equals(response.body().getHeWeather6().get(0).getStatus())) {
            if (response.body().getHeWeather6().get(0).getBasic() != null) {//得到数据不为空则进行数据显示
                /**
                 * 当天天气
                 */
                tvTemperature.setText(response.body().getHeWeather6().get(0).getNow().getTmp());//温度
                if (flag) {
                    ivLocation.setVisibility(View.VISIBLE);//显示定位图标
                } else {
                    ivLocation.setVisibility(View.GONE);//显示定位图标
                }
                tvCity.setText(response.body().getHeWeather6().get(0).getBasic().getLocation());//城市
                tvInfo.setText(response.body().getHeWeather6().get(0).getNow().getCond_txt());//天气状况
                //修改上次更新时间的结果显示 -> 更加人性化
                String datetime = response.body().getHeWeather6().get(0).getUpdate().getLoc();//赋值
                String time = datetime.substring(11);//截去前面的字符,保留后面所有的字符,就剩下 22:00
                tvOldTime.setText("上次更新时间:" + WeatherUtil.showTimeInfo(time) + time);
                tvWindDirection.setText("风向     " + response.body().getHeWeather6().get(0).getNow().getWind_dir());//风向
                tvWindPower.setText("风力     " + response.body().getHeWeather6().get(0).getNow().getWind_sc() + "级");//风力
                wwBig.startRotate();//大风车开始转动
                wwSmall.startRotate();//小风车开始转动
                /**
                 * 查询7天天气预报
                 */
                //最低温和最高温
                tvLowHeight.setText(response.body().getHeWeather6().get(0).getDaily_forecast().get(0).getTmp_min() + " / " +
                        response.body().getHeWeather6().get(0).getDaily_forecast().get(0).getTmp_max() + "℃");
                if (response.body().getHeWeather6().get(0).getDaily_forecast() != null) {
                    List<WeatherResponse.HeWeather6Bean.DailyForecastBean> data
                            = response.body().getHeWeather6().get(0).getDaily_forecast();
                    mListDailyForecast.clear();//添加数据之前先清除
                    mListDailyForecast.addAll(data);//添加数据
                    mAdapter.notifyDataSetChanged();//刷新列表
                } else {
                    ToastUtils.showShortToast(context, "天气预报数据为空");
                }
                /**
                 * 查询逐小时天气数据
                 */
                if (response.body().getHeWeather6().get(0).getHourly() != null) {
                    List<WeatherResponse.HeWeather6Bean.HourlyBean> data
                            = response.body().getHeWeather6().get(0).getHourly();
                    mListHourlyBean.clear();//添加数据之前先清除
                    mListHourlyBean.addAll(data);//添加数据
                    mAdapterHourly.notifyDataSetChanged();//刷新列表
                } else {
                    ToastUtils.showShortToast(context, "逐小时预报数据为空");
                }
                /**
                 * 生活指数
                 */
                List<WeatherResponse.HeWeather6Bean.LifestyleBean> data = response.body().getHeWeather6().get(0).getLifestyle();
                if (!ObjectUtils.isEmpty(data)) {
                    for (int i = 0; i < data.size(); i++) {
                        switch (data.get(i).getType()){
                            case "uv":
                                tvUv.setText("紫外线:" + data.get(i).getTxt());
                                break;
                            case "comf":
                                tvComf.setText("舒适度:" + data.get(i).getTxt());
                                break;
                            case "drsg":
                                tvDrsg.setText("穿衣指数:" + data.get(i).getTxt());
                                break;
                            case "flu":
                                tvFlu.setText("感冒指数:" + data.get(i).getTxt());
                                break;
                            case "sport":
                                tvSport.setText("运动指数:" + data.get(i).getTxt());
                                break;
                            case "trav":
                                tvTrav.setText("旅游指数:" + data.get(i).getTxt());
                                break;
                            case "cw":
                                tvCw.setText("洗车指数:" + data.get(i).getTxt());
                                break;
                            case "air":
                                tvAir.setText("空气指数:" + data.get(i).getTxt());
                                break;
                        }
                    }
                } else {
                    ToastUtils.showShortToast(context, "生活指数数据为空");
                }
            }else {
                ToastUtils.showShortToast(context,"天气数据为空");
            }
        }else {
            ToastUtils.showShortToast(context, CodeToStringUtils.WeatherCode(response.body().getHeWeather6().get(0).getStatus()));
        }


改到这里就是初步改完了,运行一下:

20200516160715628.png

20200516160742181.png

20200516160804494.png


很明显,和之前什么变化都没有,但是,里面的业务处理方式发生了改变,之前是一次性请求四次接口,现在是变成一个接口了,无疑在机制上有了优化,现在就可以注释掉其他的代码了。

打开ApiService

20200516161238927.png


这里将之前的四个API注释掉。

再打开订阅器

20200516161451860.png

20200516161539836.png

然后再回到MainActivity

20200516161926997.png


将这四个报错的返回方法注释掉,这是你的页面是不会有报错的,然后再运行一下,确保没有问题。好了,已经运行过没有问题了,那么最后就是删除掉注释的代码了。


20200516162937925.png


这四个实体bean也可以删除了,删除之后再运行一下,OK,没有问题。也算是为应用做了一次瘦身了,下面就是优化一下用户的体验。


优化UI


增加逐小时天气预报详情和七天天气预报详情,

这个我打算用弹窗来做,首先是逐小时天气预报的详情,创建一个弹窗的背景样式

在项目的drawable下创建shape_white_5.xml文件

样式代码如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="5dp" />
    <solid android:color="#FFF" />
</shape>


① 逐小时天气预报的详情UI


在项目的layout文件下创建window_hourly_detail.xml文件

布局代码如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@drawable/shape_white_5"
    android:padding="@dimen/dp_12"
    android:layout_width="300dp"
    android:layout_height="400dp">
    <TextView
        android:gravity="center_vertical"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_16"
        android:textStyle="bold"
        android:id="@+id/tv_time"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"/>
    <!--温度-->
    <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_tem"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--天气状况-->
    <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_cond_txt"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风向360角度-->
    <LinearLayout
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <TextView
            android:text="风向360角度"
            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_wind_deg"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风向-->
    <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_wind_dir"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风力-->
    <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_wind_sc"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风速-->
    <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_wind_spd"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--相对湿度-->
    <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_hum"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--大气压强-->
    <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_pres"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--降水概率-->
    <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_pop"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--露点温度-->
    <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_dew"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--云量-->
    <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>
</LinearLayout>


由于这一次的弹窗是屏幕中间出现,所以增加动画效果和代码,在mvplibrary模块下的anim文件夹中增加出现和隐藏的动画xml文件

20200527180259981.png


window_hidden_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="300"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0.5"
        android:toYScale="0.5" />
    <alpha
        android:duration="300"
        android:fromAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="0.0" />
</set>


window_show_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="300"
        android:fromXScale="0.6"
        android:fromYScale="0.6"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />
    <alpha
        android:duration="300"
        android:fromAlpha="0.0"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:toAlpha="1.0" />
</set>


然后在styles.xml文件中添加


20200527180634382.png


这里还会用到一个测量的工具类SizeUtils.java


代码如下:

package com.llw.mvplibrary.utils;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
/**
 * dp sp px 转换 view 测量工个类
 */
public final class SizeUtils {
    private SizeUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }
    /**
     * Value of dp to value of px.
     *
     * @param dpValue The value of dp.
     * @return value of px
     */
    public static int dp2px(Context context, final float dpValue) {
        final float scale = context.getApplicationContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    /**
     * Value of px to value of dp.
     *
     * @param pxValue The value of px.
     * @return value of dp
     */
    public static int px2dp(Context context, final float pxValue) {
        final float scale = context.getApplicationContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
    /**
     * Value of sp to value of px.
     *
     * @param spValue The value of sp.
     * @return value of px
     */
    public static int sp2px(Context context, final float spValue) {
        final float fontScale = context.getApplicationContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
    /**
     * Value of px to value of sp.
     *
     * @param pxValue The value of px.
     * @return value of sp
     */
    public static int px2sp(Context context, final float pxValue) {
        final float fontScale = context.getApplicationContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }
    /**
     * Converts an unpacked complex data value holding a dimension to its final floating
     * point value. The two parameters <var>unit</var> and <var>value</var>
     * are as in {@link TypedValue#TYPE_DIMENSION}.
     *
     * @param value The value to apply the unit to.
     * @param unit  The unit to convert from.
     * @return The complex floating point value multiplied by the appropriate
     * metrics depending on its unit.
     */
    public static float applyDimension(Context context, final float value, final int unit) {
        DisplayMetrics metrics = context.getApplicationContext().getResources().getDisplayMetrics();
        switch (unit) {
            case TypedValue.COMPLEX_UNIT_PX:
                return value;
            case TypedValue.COMPLEX_UNIT_DIP:
                return value * metrics.density;
            case TypedValue.COMPLEX_UNIT_SP:
                return value * metrics.scaledDensity;
            case TypedValue.COMPLEX_UNIT_PT:
                return value * metrics.xdpi * (1.0f / 72);
            case TypedValue.COMPLEX_UNIT_IN:
                return value * metrics.xdpi;
            case TypedValue.COMPLEX_UNIT_MM:
                return value * metrics.xdpi * (1.0f / 25.4f);
        }
        return 0;
    }
    /**
     * Force get the size of view.
     * <p>e.g.</p>
     * <pre>
     * SizeUtils.forceGetViewSize(view, new SizeUtils.onGetSizeListener() {
     *     Override
     *     public void onGetSize(final View view) {
     *         view.getWidth();
     *     }
     * });
     * </pre>
     *
     * @param view     The view.
     * @param listener The get size listener.
     */
    public static void forceGetViewSize(final View view, final onGetSizeListener listener) {
        view.post(new Runnable() {
            @Override
            public void run() {
                if (listener != null) {
                    listener.onGetSize(view);
                }
            }
        });
    }
    /**
     * Return the width of view.
     *
     * @param view The view.
     * @return the width of view
     */
    public static int getMeasuredWidth(final View view) {
        return measureView(view)[0];
    }
    /**
     * Return the height of view.
     *
     * @param view The view.
     * @return the height of view
     */
    public static int getMeasuredHeight(final View view) {
        return measureView(view)[1];
    }
    /**
     * Measure the view.
     *
     * @param view The view.
     * @return arr[0]: view's width, arr[1]: view's height
     */
    public static int[] measureView(final View view) {
        ViewGroup.LayoutParams lp = view.getLayoutParams();
        if (lp == null) {
            lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT
            );
        }
        int widthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
        int lpHeight = lp.height;
        int heightSpec;
        if (lpHeight > 0) {
            heightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY);
        } else {
            heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        }
        view.measure(widthSpec, heightSpec);
        return new int[]{view.getMeasuredWidth(), view.getMeasuredHeight()};
    }
    ///
    // interface
    ///
    public interface onGetSizeListener {
        void onGetSize(View view);
    }
}


现在去LiWindow.java中增加中间显示的代码.


20200527180905167.png


增加的代码我也贴一下:

  /**
     * 中间显示
     * @param mView
     */
    public void showCenterPopupWindow(View mView,int width,int height) {
        mPopupWindow = new PopupWindow(mView,
                width, height, true);
        mPopupWindow.setContentView(mView);
        mPopupWindow.setAnimationStyle(R.style.AnimationCenterFade); //设置动画
        mPopupWindow.showAtLocation(mView, Gravity.CENTER, 0, 0);
        mPopupWindow.update();
        setBackgroundAlpha(0.5f,mContext);
        WindowManager.LayoutParams nomal = ((Activity) mContext).getWindow().getAttributes();
        nomal.alpha = 0.5f;
        ((Activity) mContext).getWindow().setAttributes(nomal);
        mPopupWindow.setOnDismissListener(closeDismiss);
    }


现在修改item_weather_hourly_list.xml,增加了一个id和点击的水波纹效果,代码如下,复制粘贴即可:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:id="@+id/item_hourly"
    android:foreground="@drawable/bg_white"
    android:padding="8dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <!--时间-->
    <TextView
        android:id="@+id/tv_time"
        android:textColor="#FFF"
        android:text="上午10:00"
        android:textSize="14sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <!--气候图标-->
    <ImageView
        android:layout_marginTop="12dp"
        android:layout_marginBottom="8dp"
        android:id="@+id/iv_weather_state"
        android:background="@mipmap/icon_100"
        android:layout_width="30dp"
        android:layout_height="30dp"/>
    <!--温度-->
    <TextView
        android:textSize="20sp"
        android:id="@+id/tv_temperature"
        android:textColor="#FFF"
        android:text="25℃"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>


再修改WeatherHourlyAdapter.java适配器


20200527181219602.png


添加点击事件的id。

进入MainActivity.java


20200527181435221.png


这个代码就手写一下吧,也不多,然后是这个弹窗的方法

  //显示逐三小时详情天气信息弹窗
    private void showHourlyWindow(WeatherResponse.HeWeather6Bean.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 datetime = data.getTime();//赋值
        String time = datetime.substring(11);//截去前面的字符,保留后面所有的字符,就剩下 22:00
        tv_time.setText(WeatherUtil.showTimeInfo(time) + time);
        tv_tem.setText(data.getTmp() + "℃");
        tv_cond_txt.setText(data.getCond_txt());
        tv_wind_deg.setText(data.getWind_deg()+"°");
        tv_wind_dir.setText(data.getWind_dir());
        tv_wind_sc.setText(data.getWind_sc()+"级");
        tv_wind_spd.setText(data.getWind_spd() + "公里/小时");
        tv_hum.setText(data.getHum());
        tv_pres.setText(data.getPres());
        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));
    }


OK,到目前为止,可以运行一下了

20200528090618966.png


OK,还是蛮简单的吧(PS:由于没有UI,大家这个都知道开发的审美,就先将就一下,如果有好的建议可以给我提)。


② 未来七天天气的详情UI


其实这个和逐小时的比较类似,不过要比逐小时的数据要多一些,

在项目的layout文件下创建window_forecast_detail.xml文件

布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@drawable/shape_white_5"
    android:padding="@dimen/dp_12"
    android:layout_width="300dp"
    android:layout_height="500dp">
    <TextView
        android:gravity="center_vertical"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_16"
        android:textStyle="bold"
        android:id="@+id/tv_datetime"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"/>
    <!--最高温-->
    <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_tmp_max"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--最低温-->
    <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_tmp_min"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--紫外线强度-->
    <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_uv_index"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--白天天气状况-->
    <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_cond_txt_d"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--晚上天气状况-->
    <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_cond_txt_n"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风向360角度-->
    <LinearLayout
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <TextView
            android:text="风向360角度"
            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_wind_deg"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风向-->
    <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_wind_dir"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风力-->
    <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_wind_sc"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--风速-->
    <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_wind_spd"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--相对湿度-->
    <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_hum"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--大气压强-->
    <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_pres"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--降水量-->
    <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_pcpn"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--降水概率-->
    <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_pop"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <!--能见度-->
    <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_vis"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>


修改item_weather_forecast_list.xml增加ID和点击效果


20200528104807275.png


修改WeatherForecastAdapter.java,绑定点击事件的id


2020052810492163.png


这里先添加一个事件日期的工具类进去,是我好久之前写的,不过也能用的上DateUtils.java,代码如下:


package com.llw.goodweather.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
public class DateUtils {
    //获取当前完整的日期和时间
    public static String getNowDateTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date());
    }
    //获取当前日期
    public static String getNowDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }
    //前一天
    public static String getYesterday(Date date) {
        String tomorrow = "";
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1);
        date = calendar.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        tomorrow = formatter.format(date);
        return tomorrow;
    }
    //后一天
    public static String getTomorrow(Date date) {
        String tomorrow = "";
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, +1);
        date = calendar.getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        tomorrow = formatter.format(date);
        return tomorrow;
    }
    //获取当前时间
    public static String getNowTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        return sdf.format(new Date());
    }
    //获取当前日期(精确到毫秒)
    public static String getNowTimeDetail() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        return sdf.format(new Date());
    }
    //获取今天是星期几
    public static String getWeekOfDate(Date date) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }
    //计算星期几
    private static int getDayOfWeek(String dateTime) {
        Calendar cal = Calendar.getInstance();
        if (dateTime.equals("")) {
            cal.setTime(new Date(System.currentTimeMillis()));
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
            Date date;
            try {
                date = sdf.parse(dateTime);
            } catch (ParseException e) {
                date = null;
                e.printStackTrace();
            }
            if (date != null) {
                cal.setTime(new Date(date.getTime()));
            }
        }
        return cal.get(Calendar.DAY_OF_WEEK);
    }
    //根据年月日计算是星期几并与当前日期判断  非昨天、今天、明天 则以星期显示
    public static String Week(String dateTime) {
        String week = "";
        String yesterday = "";
        String today = "";
        String tomorrow = "";
        yesterday = getYesterday(new Date());
        today = getNowDate();
        tomorrow = getTomorrow(new Date());
        if (dateTime.equals(yesterday)) {
            week = "昨天";
        } else if (dateTime.equals(today)) {
            week = "今天";
        } else if (dateTime.equals(tomorrow)) {
            week = "明天";
        } else {
            switch (getDayOfWeek(dateTime)) {
                case 1:
                    week = "星期日";
                    break;
                case 2:
                    week = "星期一";
                    break;
                case 3:
                    week = "星期二";
                    break;
                case 4:
                    week = "星期三";
                    break;
                case 5:
                    week = "星期四";
                    break;
                case 6:
                    week = "星期五";
                    break;
                case 7:
                    week = "星期六";
                    break;
            }
        }
        return week;
    }
    //将时间戳转化为对应的时间(10位或者13位都可以)
    public static String formatTime(long time) {
        String times = null;
        if (String.valueOf(time).length() > 10) {// 10位的秒级别的时间戳
            times = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000));
        } else {// 13位的秒级别的时间戳
            times = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
        }
        return times;
    }
    //将时间字符串转为时间戳字符串
    public static String getStringTimestamp(String time) {
        String timestamp = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Long longTime = sdf.parse(time).getTime() / 1000;
            timestamp = Long.toString(longTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return timestamp;
    }
}


修改MainActivity.java

20200528105221999.png


这里添加的代码,你就手写一下吧,至于里面的showForecastWindow,代码如下:

  //显示天气预报详情弹窗
    private void showForecastWindow(WeatherResponse.HeWeather6Bean.DailyForecastBean 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_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);//降水概率
        TextView tv_vis = view.findViewById(R.id.tv_vis);//能见度
        tv_datetime.setText(data.getDate() +"   "+ DateUtils.Week(data.getDate()));//时间日期
        tv_tmp_max.setText(data.getTmp_max() + "℃");
        tv_tmp_min.setText(data.getTmp_min() + "℃");
        tv_uv_index.setText(data.getUv_index());
        tv_cond_txt_d.setText(data.getCond_txt_d());
        tv_cond_txt_n.setText(data.getCond_txt_n());
        tv_wind_deg.setText(data.getWind_deg() + "°");
        tv_wind_dir.setText(data.getWind_dir());
        tv_wind_sc.setText(data.getWind_sc() + "级");
        tv_wind_spd.setText(data.getWind_spd() + "公里/小时");
        tv_hum.setText(data.getHum());
        tv_pres.setText(data.getPres());
        tv_pcpn.setText(data.getPcpn());
        tv_pop.setText(data.getPop() + "%");
        tv_vis.setText(data.getVis());
        liWindow.showCenterPopupWindow(view, SizeUtils.dp2px(context, 300), SizeUtils.dp2px(context, 500));
    }


运行效果如下:


20200528105432119.png

20200528105951711.png


到了这里,天气APP的第十四篇文章就写完了,感触良多啊,

相关文章
|
5天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
1月前
|
Linux 开发工具 数据安全/隐私保护
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
这篇文章介绍了在CentOS 7系统中安装Docker时遇到的两个常见问题及其解决方法:用户不在sudoers文件中导致权限不足,以及yum被锁定的问题。
38 2
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
|
2月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
65 1
|
3月前
|
JavaScript Linux 数据中心
【Azure Function App】解决Function App For Container 遇见ServiceUnavailable的异常
【Azure Function App】解决Function App For Container 遇见ServiceUnavailable的异常
【Azure Function App】解决Function App For Container 遇见ServiceUnavailable的异常
|
3月前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
3月前
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
56 1
|
3月前
|
API Android开发
Android项目架构设计问题之选择和使用合适的UI库如何解决
Android项目架构设计问题之选择和使用合适的UI库如何解决
48 0
|
3月前
|
API
【Azure 应用服务】在App Service中调用外部服务API时需要携带客户端证书,而多次调用的情况下会出现WindowsCryptographicException Keyset does not exist异常
【Azure 应用服务】在App Service中调用外部服务API时需要携带客户端证书,而多次调用的情况下会出现WindowsCryptographicException Keyset does not exist异常
|
3月前
|
C# 开发工具
【Azure 应用服务】Azure Function App使用SendGrid发送邮件遇见异常消息The operation was canceled,分析源码渐入最源端
【Azure 应用服务】Azure Function App使用SendGrid发送邮件遇见异常消息The operation was canceled,分析源码渐入最源端
|
4月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
【7月更文挑战第28天】随着移动应用市场的发展,用户对界面设计的要求不断提高。Material Design是由Google推出的设计语言,强调真实感、统一性和创新性,通过模拟纸张和墨水的物理属性创造沉浸式体验。它注重色彩、排版、图标和布局的一致性,确保跨设备的统一视觉风格。Android Studio提供了丰富的Material Design组件库,如按钮、卡片等,易于使用且美观。
143 1