Android 天气APP(五)天气预报、生活指数的数据请求与渲染(上)

简介: Android 天气APP(五)天气预报、生活指数的数据请求与渲染(上)

天气预报、生活指数的数据请求与渲染


6. 天气预报


① 新增API接口

② 修改订阅器

③ 修改布局,增加列表和适配器

④ 使用适配器进行数据展示


7. 生活指数


① 新增API接口

② 修改订阅器

③ 修改布局

④ 数据渲染显示


6. 天气预报


天气预报是预测未来几天的天气,常用列表显示,实现这个功能的业务逻辑是:访问API、获取返回值、列表配置、数据渲染。首先是API接口。


① 新增API接口

根据和风天气中的文档,得知未来3-7天的天气预报接口为:


https://free-api.heweather.net/s6/weather/forecast?key=3086e91d66c04ce588a7f538f917c7f4&location=福田区

在网页上访问得到返回值,生成一个实体


20200403160550921.png


代码如下:


package com.llw.goodweather.bean;
import java.util.List;
public class WeatherForecastResponse {
    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":"CN101280603","location":"福田","parent_city":"深圳","admin_area":"广东","cnty":"中国","lat":"22.5410099","lon":"114.05095673","tz":"+8.00"}
         * update : {"loc":"2019-11-19 19:57","utc":"2019-11-19 11:57"}
         * status : ok
         * daily_forecast : [{"cond_code_d":"100","cond_code_n":"101","cond_txt_d":"晴","cond_txt_n":"多云","date":"2019-11-19","hum":"50","mr":"23:52","ms":"12:27","pcpn":"0.0","pop":"20","pres":"1012","sr":"06:39","ss":"17:38","tmp_max":"22","tmp_min":"16","uv_index":"5","vis":"25","wind_deg":"31","wind_dir":"东北风","wind_sc":"3-4","wind_spd":"17"},{"cond_code_d":"101","cond_code_n":"101","cond_txt_d":"多云","cond_txt_n":"多云","date":"2019-11-20","hum":"67","mr":"00:00","ms":"13:14","pcpn":"0.0","pop":"3","pres":"1011","sr":"06:40","ss":"17:38","tmp_max":"24","tmp_min":"16","uv_index":"4","vis":"25","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"5"},{"cond_code_d":"101","cond_code_n":"101","cond_txt_d":"多云","cond_txt_n":"多云","date":"2019-11-21","hum":"73","mr":"00:54","ms":"13:57","pcpn":"0.0","pop":"2","pres":"1009","sr":"06:40","ss":"17:38","tmp_max":"26","tmp_min":"19","uv_index":"3","vis":"25","wind_deg":"-1","wind_dir":"无持续风向","wind_sc":"1-2","wind_spd":"2"}]
         */
        private BasicBean basic;
        private UpdateBean update;
        private String status;
        private List<DailyForecastBean> daily_forecast;
        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 List<DailyForecastBean> getDaily_forecast() {
            return daily_forecast;
        }
        public void setDaily_forecast(List<DailyForecastBean> daily_forecast) {
            this.daily_forecast = daily_forecast;
        }
        public static class BasicBean {
            /**
             * cid : CN101280603
             * location : 福田
             * parent_city : 深圳
             * admin_area : 广东
             * cnty : 中国
             * lat : 22.5410099
             * lon : 114.05095673
             * 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 : 2019-11-19 19:57
             * utc : 2019-11-19 11:57
             */
            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 DailyForecastBean {
            /**
             * cond_code_d : 100
             * cond_code_n : 101
             * cond_txt_d : 晴
             * cond_txt_n : 多云
             * date : 2019-11-19
             * hum : 50
             * mr : 23:52
             * ms : 12:27
             * pcpn : 0.0
             * pop : 20
             * pres : 1012
             * sr : 06:39
             * ss : 17:38
             * tmp_max : 22
             * tmp_min : 16
             * uv_index : 5
             * vis : 25
             * wind_deg : 31
             * wind_dir : 东北风
             * wind_sc : 3-4
             * wind_spd : 17
             */
            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;
            }
        }
    }
}


接下来在ApiService中添加


2020040316092049.png


代码如下:


  /**
     * 未来3 - 7天天气预报
     */
    @GET("/s6/weather/forecast?key=3086e91d66c04ce588a7f538f917c7f4")
    Call<WeatherForecastResponse> getWeatherForecast(@Query("location") String location);


② 修改订阅器


接下来修改订阅器WeatherContract


20200403161409590.png


20200403161436863.png


WeatherContract代码如下:


package com.llw.goodweather.contract;
import android.content.Context;
import com.llw.goodweather.api.ApiService;
import com.llw.goodweather.bean.TodayResponse;
import com.llw.goodweather.bean.WeatherForecastResponse;
import com.llw.mvplibrary.base.BasePresenter;
import com.llw.mvplibrary.base.BaseView;
import com.llw.mvplibrary.net.NetCallBack;
import com.llw.mvplibrary.net.ServiceGenerator;
import retrofit2.Call;
import retrofit2.Response;
/**
 * 天气订阅器
 */
public class WeatherContract {
    public static class WeatherPresenter extends BasePresenter<IWeatherView> {
        /**
         * 当日天气
         * @param context
         * @param location  区/县
         */
        public void todayWeather(final Context context, String location) {
            //得到构建之后的网络请求服务,这里的地址已经拼接完成,只差一个location了
            ApiService service = ServiceGenerator.createService(ApiService.class);
            //设置请求回调  NetCallBack是重写请求回调
            service.getTodayWeather(location).enqueue(new NetCallBack<TodayResponse>() {
                //成功回调
                @Override
                public void onSuccess(Call<TodayResponse> call, Response<TodayResponse> response) {
                    if (getView() != null) {//当视图不会空时返回请求数据
                        getView().getTodayWeatherResult(response);
                    }
                }
                //失败回调
                @Override
                public void onFailed() {
                    if (getView() != null) {//当视图不会空时获取错误信息
                        getView().getDataFailed();
                    }
                }
            });
        }
        /**
         * 天气预报  3-7天(白嫖的就只能看到3天)
         * @param context
         * @param location
         */
        public void weatherForecast(final Context context,String location){
            ApiService service = ServiceGenerator.createService(ApiService.class);
            service.getWeatherForecast(location).enqueue(new NetCallBack<WeatherForecastResponse>() {
                @Override
                public void onSuccess(Call<WeatherForecastResponse> call, Response<WeatherForecastResponse> response) {
                    if(getView() != null){
                        getView().getWeatherForecastResult(response);
                    }
                }
                @Override
                public void onFailed() {
                    if(getView() != null){
                        getView().getDataFailed();
                    }
                }
            });
        }
    }
    public interface IWeatherView extends BaseView {
        //查询当天天气的数据返回
        void getTodayWeatherResult(Response<TodayResponse> response);
        //查询天气预报的数据返回
        void getWeatherForecastResult(Response<WeatherForecastResponse> response);
        //错误返回
        void getDataFailed();
    }
}


接下来修改布局,增加列表和适配器


③ 修改布局,增加列表和适配器


20200403165022727.png


代码中


20200403165140933.png


这个时候你的MainActivity.java会报错


20200403165241971.png


这是因为订阅器里面的内容没有写入。鼠标点击,Alt + Enter


2020040316535826.png


20200403165434659.png


20200403165514845.png


接下来创建列表的item


在layout目录下创建item_weather_forecast_list.xml文件


20200403173856891.png


代码如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:padding="@dimen/sp_12"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!--日期-->
        <TextView
            android:id="@+id/tv_date"
            android:text="1234"
            android:textSize="@dimen/sp_14"
            android:textColor="#FFF"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
        <!--天气描述-->
        <TextView
            android:gravity="center"
            android:id="@+id/tv_info"
            android:textSize="@dimen/sp_14"
            android:textColor="#FFF"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
        <!--最低温、最高温-->
        <TextView
            android:gravity="right"
            android:id="@+id/tv_low_and_height"
            android:textSize="@dimen/sp_14"
            android:textColor="#FFF"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>


接下来创建一个适配器


com.llw.goodweather下新建一个WeatherForecastAdapter适配器


20200403174111319.png


代码如下:


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.WeatherForecastResponse;
import java.util.List;
/**
 * 天气预报列表展示适配器
 */
public class WeatherForecastAdapter extends BaseQuickAdapter<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean, BaseViewHolder> {
    public WeatherForecastAdapter(int layoutResId, @Nullable List<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean> data) {
        super(layoutResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, WeatherForecastResponse.HeWeather6Bean.DailyForecastBean item) {
        helper.setText(R.id.tv_date, item.getDate())//日期
                .setText(R.id.tv_info, item.getCond_txt_d())//天气
                .setText(R.id.tv_low_and_height, item.getTmp_min() + "/" + item.getTmp_max() + "℃");//最低温和最高温
    }
}


④ 使用适配器进行数据展示


在MainActivity.java中增加


  List<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean> mList;//初始化数据源
    WeatherForecastAdapter mAdapter;//初始化适配器
  /**
     * 初始化天气预报数据列表
     */
    private void initList() {
        mList = new ArrayList<>();//声明为ArrayList
        mAdapter = new WeatherForecastAdapter(R.layout.item_weather_forecast_list, mList);//为适配器设置布局和数据源
        LinearLayoutManager manager = new LinearLayoutManager(context);//布局管理,默认是纵向
        rv.setLayoutManager(manager);//为列表配置管理器
        rv.setAdapter(mAdapter);//为列表配置适配器
    }


然后在**initData()**方法中调用

20200403175400979.png

20200403180309415.png


返回值做处理


  //查询天气预报,请求成功后的数据返回
    @Override
    public void getWeatherForecastResult(Response<WeatherForecastResponse> response) {
        if (("ok").equals(response.body().getHeWeather6().get(0).getStatus())) {
            //最低温和最高温
            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<WeatherForecastResponse.HeWeather6Bean.DailyForecastBean> data
                        = response.body().getHeWeather6().get(0).getDaily_forecast();
                mList.clear();//添加数据之前先清除
                mList.addAll(data);//添加数据
                mAdapter.notifyDataSetChanged();//刷新列表
            } else {
                ToastUtils.showShortToast(context, "天气预报数据为空");
            }
        } else {
            ToastUtils.showShortToast(context, response.body().getHeWeather6().get(0).getStatus());
        }
    }


运行


2020040318051015.png


这样天气预报这个功能就完成了。


接下来是生活指数。

相关文章
|
11天前
|
Windows
【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释
在Azure App Service中,CPU占比可在App Service Plan级别查看整个实例的资源使用情况。具体应用中仅能查看CPU时间,需通过公式【CPU Time / (CPU核数 * 60)】估算占比。CPU百分比适用于可横向扩展的计划(Basic、Standard、Premium),而CPU时间适用于Free或Shared计划。然而,CPU Percentage包含所有应用及系统占用的CPU,高CPU指标可能由系统而非应用请求引起。详细分析每个进程的CPU占用需抓取Windows Performance Trace数据。
75 40
|
7天前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
24天前
|
存储 监控 API
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
app开发之安卓Android+苹果ios打包所有权限对应解释列表【长期更新】-以及默认打包自动添加权限列表和简化后的基本打包权限列表以uniapp为例-优雅草央千澈
|
3月前
|
JSON API 网络安全
App数据的爬取
App数据的爬取
51 3
|
3月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
504 0
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
3天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
70 19
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
74 14

热门文章

最新文章