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


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


接下来是生活指数。

相关文章
|
23天前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
41 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
10天前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
|
14天前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
35 3
|
8天前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
6天前
|
移动开发 Android开发 数据安全/隐私保护
移动应用与系统的技术演进:从开发到操作系统的全景解析随着智能手机和平板电脑的普及,移动应用(App)已成为人们日常生活中不可或缺的一部分。无论是社交、娱乐、购物还是办公,移动应用都扮演着重要的角色。而支撑这些应用运行的,正是功能强大且复杂的移动操作系统。本文将深入探讨移动应用的开发过程及其背后的操作系统机制,揭示这一领域的技术演进。
本文旨在提供关于移动应用与系统技术的全面概述,涵盖移动应用的开发生命周期、主要移动操作系统的特点以及它们之间的竞争关系。我们将探讨如何高效地开发移动应用,并分析iOS和Android两大主流操作系统的技术优势与局限。同时,本文还将讨论跨平台解决方案的兴起及其对移动开发领域的影响。通过这篇技术性文章,读者将获得对移动应用开发及操作系统深层理解的钥匙。
|
9天前
|
XML 移动开发 前端开发
使用duxapp开发 React Native App 事半功倍
对于Taro的壳子,或者原生React Native,都会存在 `android` `ios`这两个文件夹,而在duxapp中,这些文件夹的内容是自动生成的,那么对于需要在这些文件夹中修改的配置内容,例如包名、版本号、新架构开关等,都通过配置文件的方式配置了,而不需要需修改具体的文件
|
1月前
|
Web App开发 Java 视频直播
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
对于软件、计算机等专业的毕业生,毕业设计需实现实用软件或APP。新颖的设计应结合最新技术,如5G时代的音视频技术。示例包括: 1. **短视频分享APP**: 集成FFmpeg实现视频剪辑功能,如添加字幕、转场特效等。 2. **电商购物APP**: 具备直播带货功能,使用RTMP/SRT协议支持流畅直播体验。 3. **同城生活APP**: 引入WebRTC技术实现可信的视频通话功能。这些应用不仅实用,还能展示开发者紧跟技术潮流的能力。
69 4
FFmpeg开发笔记(四十九)助您在毕业设计中脱颖而出的几个流行APP
|
29天前
|
移动开发 小程序 JavaScript
uni-app开发微信小程序
本文详细介绍如何使用 uni-app 开发微信小程序,涵盖需求分析、架构思路及实施方案。主要功能包括用户登录、商品列表展示、商品详情、购物车及订单管理。技术栈采用 uni-app、uView UI 和 RESTful API。文章通过具体示例代码展示了从初始化项目、配置全局样式到实现各页面组件及 API 接口的全过程,并提供了完整的文件结构和配置文件示例。此外,还介绍了微信授权登录及后端接口模拟方法,确保项目的稳定性和安全性。通过本教程,读者可快速掌握使用 uni-app 开发微信小程序的方法。
57 3
|
2月前
|
Web App开发 Android开发
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo
实时数据传输在互联网中至关重要,不仅支持即时通讯如QQ、微信的文字与图片传输,还包括音视频通信。一对一通信常采用WebRTC技术,如《Android Studio开发实战》中的App集成示例;而一对多的在线直播则需部署独立的流媒体服务器,使用如SRT等协议。SRT因其优越的直播质量正逐渐成为主流。本文档概述了SRT协议的使用,包括通过OBS Studio和SRT Streamer进行SRT直播推流的方法,并展示了推流与拉流的成功实例。更多细节参见《FFmpeg开发实战》一书。
43 1
FFmpeg开发笔记(四十六)利用SRT协议构建手机APP的直播Demo
|
2月前
|
Web App开发 5G Linux
FFmpeg开发笔记(四十四)毕业设计可做的几个拉满颜值的音视频APP
一年一度的毕业季来临,计算机专业的毕业设计尤为重要,不仅关乎学业评价还积累实战经验。选择紧跟5G技术趋势的音视频APP作为课题极具吸引力。这里推荐三类应用:一是融合WebRTC技术实现视频通话的即时通信APP;二是具备在线直播功能的短视频分享平台,涉及RTMP/SRT等直播技术;三是具有自定义动画特效及卡拉OK歌词字幕功能的视频剪辑工具。这些项目不仅技术含量高,也符合市场需求,是毕业设计的理想选择。
68 6
FFmpeg开发笔记(四十四)毕业设计可做的几个拉满颜值的音视频APP
下一篇
无影云桌面