kotlin 编写一个简单的天气预报app(五)增加forcast接口并显示

news2024/11/14 13:36:30

参考资料

OpenWeatherMap提供了一个/forecast接口,用于获取未来几天的天气预报。你可以使用HTTP GET请求访问该接口,并根据你所在的城市或地理坐标获取相应的天气数据。

以下是一个示例请求的URL和一些常用的参数:

URL: http://api.openweathermap.org/data/2.5/forecast

查询参数:

  • q (必需): 城市名称 (e.g. “London,uk”) 或城市ID (可在OpenWeatherMap网站上获得) 或地理坐标 (使用纬度和经度, e.g. “37.7749,-122.4194”)。
  • appid (必需): 你的OpenWeatherMap API密钥。
    可选参数:
    units: 温度单位 (例如 “metric” 表示摄氏度, “imperial” 表示华氏度)。
    lang: 返回的天气描述语言 (例如 “en” 表示英语)。

从openWeatherMap获取forecast

1.在WeatherService接口中增加请求函数。

getForecastByCityName:此方法与 getWeatherByCityName 方法类似,但它检索预报数据而不是当前天气数据。它还采用城市名称和 API 密钥作为参数,并返回 ForecastResponse 类型的 Call 对象,这是从 API 收到的响应。

interface WeatherService {

    @GET("weather")
    fun getWeatherByCityName(
        @Query("q") cityName : String,
        @Query("appid") apiKey : String
    ) : Call<WeatherResponse>

    @GET("forecast")
    fun getForecastByCityName(
        @Query("q") cityName : String,
        @Query("appid") apiKey : String
    ) : Call<ForecastResponse>
}

2.编译一个新的ForecastResponse 类,用于解析天气预报的 JSON 数据。它具有以下属性:

  • cod:表示响应 JSON 中的 cod 值的字符串变量。
  • message:表示响应 JSON 中的消息值的整数变量。
  • cnt:表示响应 JSON 中的 cnt 值的整数变量。
  • forecastCellList:ForecastCell 对象的ArrayList,表示响应JSON 中的预测单元格列表。
  • forecastCity:ForecastCity 对象,表示响应 JSON 中的城市详细信息。
    这些属性使用 @SerializedName 进行注释,以指定 JSON 中相应的键。提供默认值是为了初始化目的。
package com.example.myweather.openWeatherMap

import com.example.myweather.WeatherResponseClouds
import com.example.myweather.WeatherResponseCoord
import com.example.myweather.WeatherResponseWeather
import com.google.gson.annotations.SerializedName

data class ForecastResponse (
    @SerializedName("cod")
    var cod: String = "",
    @SerializedName("message")
    var message: Int = 0,
    @SerializedName("cnt")
    var cnt : Int = 0,
    @SerializedName("list")
    var forecastCellList : ArrayList<ForecastCell>? = null,
    @SerializedName("city")
    var forecastCity: ForecastCity? = null
)


data class ForecastCell (
    @SerializedName("dt")
    val dt: Long,
    @SerializedName("main")
    val main: ForecastMain,
    @SerializedName("weather")
    val weather: List<WeatherResponseWeather>,
    @SerializedName("clouds")
    val clouds: WeatherResponseClouds,
    @SerializedName("wind")
    val wind: ForecastWind,
    @SerializedName("visibility")
    val visibility: Int = 0,
    @SerializedName("pop")
    val pop: Double = 0.0,
    @SerializedName("rain")
    val rain: ForecastRain,
    @SerializedName("snow")
    val snow: ForecastSnow,
    @SerializedName("sys")
    val sys: ForecastSys,
    @SerializedName("dt_txt")
    val dt_txt: String = ""
)

data class ForecastCity(
    @SerializedName("id")
    val id: Int = 0,
    @SerializedName("name")
    val name: String = "",
    @SerializedName("coord")
    val coord: WeatherResponseCoord,
    @SerializedName("country")
    val country: String ="",
    @SerializedName("population")
    val population:Int = 0,
    @SerializedName("timezone")
    val timezone: Int = 0,
    @SerializedName("sunrise")
    val sunrise: Int = 0,
    @SerializedName("sunset")
    val sunset: Int = 0
)

data class ForecastMain(
    @SerializedName("temp")
    val temperature: Double = 0.0,
    @SerializedName("feels_like")
    val feelsLike: Double = 0.0,
    @SerializedName("temp_min")
    val minTemperature: Double = 0.0,
    @SerializedName("temp_max")
    val maxTemperature: Double = 0.0,
    @SerializedName("pressure")
    val pressure: Int = 0,
    @SerializedName("sea_level")
    val seaLevel: Int = 0,
    @SerializedName("grnd_level")
    val groundLevel: Int = 0,
    @SerializedName("humidity")
    val humidity: Int = 0,
    @SerializedName("temp_kf")
    val temperatureKf: Double = 0.0
)

data class ForecastWind(
    @SerializedName("speed")
    val speed: Double = 0.0,
    @SerializedName("deg")
    val degree: Int = 0,
    @SerializedName("gust")
    val gust : Double = 0.0
)

data class ForecastRain(
    @SerializedName("3h")
    val heightInThreeHours: Double = 0.0
)

data class ForecastSnow(
    @SerializedName("3h")
    val heightInThreeHours: Double = 0.0
)

data class ForecastSys(
    @SerializedName("pod")
    val partOfDay: String = ""
)

3.在CustomEvent.kt中增加ForecastResponseEvent事件

class ForecastResponseEvent(val forecastResponse: ForecastResponse)

4.在RetrofitClient.kt中增加getForecastByCityName函数,用来MainActivity中调用请求接口:

    fun getForecastByCityName(cityName: String) {
        val call = weatherService.getForecastByCityName(cityName, API_KEY)
        call.enqueue(object : Callback<ForecastResponse> {
            override fun onResponse(call : Call<ForecastResponse>,
                response: Response<ForecastResponse>) {
                if(response.isSuccessful) {
                    val forecastData = response.body()
                    handleForecastData(forecastData)
                } else {
                    handleForecastFailure(response.message())
                }

            }

            override fun onFailure(call: Call<ForecastResponse>, t: Throwable) {
                handleForecastFailure(t.message!!)
            }
        })

5.并且增加了相应函数

  • handleForecastFailure接受消息字符串作为参数并将其与前缀一起打印出来。
  • handleForecastData接受一个ForecastResponse对象作为参数。它检查该对象是否为空,如果不为空,则创建一个对象ForecastResponseEvent并使用 EventBus 发布它。然后它调用该printForecastResponse函数并传入该ForecastResponse对象。
  • printForecastResponse接受一个ForecastResponse对象作为参数,并打印出该对象的各种属性,例如 、cod、message和cnt的大小forecastCellList。它还打印出对象的id和属性。nameforecastCity
    private fun handleForecastFailure(message: String) {
        println("handleForecastFailure:${message}")
    }

    private fun handleForecastData(forecastData: ForecastResponse?) {
        if(forecastData == null) return

        val forecastResponseEvent = ForecastResponseEvent(forecastData)
        EventBus.getDefault().post(forecastResponseEvent)		//这里发送了forecastResponseEvent

        printForecastResponse(forecastData)
    }

    private  fun printForecastResponse(forecastResponse: ForecastResponse) {
        println("cod:${forecastResponse.cod}")
        println("message:${forecastResponse.message}")
        println("cnt:${forecastResponse.cnt}")
        println("list:${forecastResponse.forecastCellList?.size}")
        println("city id:${forecastResponse.forecastCity?.id} name:${forecastResponse.forecastCity?.name}")
    }

6.在MainActivity中,处理forecastResponseEvent事件:

该函数是一个事件处理程序,在收到onReceiveForecastResponsea 时调用。ForecastResponseEvent它采用事件对象作为参数,其中包含预测响应数据。该函数调用该updateForecastList函数根据接收到的数据更新预测列表。

updateForecastList函数接受一个ForecastResponse对象作为参数。然后,它创建一个SimpleDateFormat对象来格式化预测响应中的日期和时间。该函数初始化一个空的可变列表data来存储格式化的预测数据。

然后,该函数会迭代 的预测单元格列表中的每个单元格forecastResponse。对于每个单元格,它都会创建一个字符串,oneLine其中包含格式化的日期和时间、温度、feel_like、天气主体和天气描述。通过减去常数值并将其转换为整数,将温度从开尔文转换为摄氏度kelvins。

每个oneLine字符串都会添加到data列表中。

最后,该函数创建一个ArrayAdapter以data列表为数据源的适配器,并将其设置为ListViewID 的适配器listViewTodayForcast。这将使用更新的预测数据更新列表视图。

    @RequiresApi(Build.VERSION_CODES.O)
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onReceiveForecastResponse(event: ForecastResponseEvent) {
        updateForecastList(event.forecastResponse)
    }
    
    private fun updateForecastList(forecastResponse: ForecastResponse) {
        val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH)
        val data = mutableListOf<String>()
        for (cell in forecastResponse.forecastCellList!!) {
            val oneLine = "${simpleDateFormat.format(cell.dt*1000L)}\n" +
                    "temperature:${cell.main.temperature.minus(kelvins).toInt()}," +
                    "feel_like:${cell.main.feelsLike.minus(kelvins).toInt()},\n" +
                    "weather:${cell.weather.first().main},${cell.weather.first().description}"
            data.add(oneLine)
        }

        val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data)
        findViewById<ListView>(R.id.listViewTodayForcast).adapter = adapter
    }

7.我在主界面中增加了一个ListView用来显示forecast返回的数据

    <ListView
        android:id="@+id/listViewTodayForcast"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/textViewWeather"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

8.最后的结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/815756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AWS——01篇(AWS入门 以及 AWS之EC2实例及简单实用)

AWS——01篇&#xff08;AWS入门 以及 AWS之EC2实例及简单实用&#xff09; 1. 前言2. 创建AWS账户3. EC23.1 启动 EC2 新实例3.1.1 入口3.1.2 设置名称 选择服务3.1.3 创建密钥对3.1.4 网络设置——安全组3.1.4.1 初始设置3.1.4.2 添加安全组规则&#xff08;开放新端口&…

用Javascript和表情符号制作URL动画

您可以在URL中使用表情符号(和其他图形unicode字符)。哇&#xff0c;太棒了。但似乎没有人去做。为什么&#xff1f;或许表情符号对普通网络平台来说太陌生了&#xff1f;又或许是怕触怒SEO大神而避之不及&#xff1f; 不管是什么原因&#xff0c;维恩图上“有可能没有人做”的…

NPOI库:C#中使用的强大工具箱,从入门到精通

*引言&#xff1a; 在软件开发中&#xff0c;Excel文件是一种常见且重要的数据存储和处理方式。为了简化Excel文件的读写操作&#xff0c;C --------------------------目录-------------------------- 一、安装NPOI库二、引入命名空间三、Excel文件的读取1. 打开Excel文件2. 读…

抄袭可耻,尊重原创

抄袭者的博客主页链接&#xff1a;MISAYAONE_OD机试 Py/Java/JS合集&#xff08;A卷B卷&#xff09;,华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;,华为OD机试&#xff08;Python&#xff09;真题&#xff08;A卷B卷&#xff09;-CSDN博客 这个博…

30个前端开发中常用的JavaScript函数

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 前言 在前端开发中通常会用到校验函数…

纯干货!打造TikTok爆款视频的是个要素!(记得收藏)

Tik Tok在海外经历了一系列遭遇引发了全球的关注&#xff0c;作为一款针对年轻受众的短视频分享应用&#xff0c;仅用3年多的时间在美国的用户数量就突破1亿&#xff0c;在今年一季度还成为全球下载量最高的移动应用。 在过去一年中&#xff0c;Tik Tok的新闻和热门视频频频出…

玩转新时代兴趣社交,伴伴打造新赛道

随着时代的发展&#xff0c;人们对于社交的需求也在不断地增加。从面对面社交到社交软件聊天再到现在的兴趣社交&#xff0c;无一不体现着年轻人多元化的社交需求。作为社交软件的行业龙头之一&#xff0c;伴伴平台为用户打造多元化社交场景&#xff0c;以兴趣作为社交的出发点…

Docker的安装和部署

目录 一、Docker的安装部署 &#xff08;1&#xff09;关闭防火墙 &#xff08;2&#xff09;关闭selinux &#xff08;3&#xff09;安装docker引擎 &#xff08;4&#xff09;启动docker &#xff08;5&#xff09;设置docker自启动 &#xff08;6&#xff09;测试doc…

TopSolid2021安装

安装TopSolid&#xff0c;选择要安装的功能&#xff0c;一般只安装Design即可&#xff0c;然后在“工具”选项卡一般只选择图示的两个就可以了 使用管理员权限运行文件 “TopSolid2021\Setup\Redist\Sentinel RMS License Manager\Tools\WlmAdmin.exe” 按图示操作&#xff1…

服务器运行python程序的使用说明

服务器的使用与说明 文章目录 服务器的使用与说明1.登录2.Python的使用2.1 服务器已安装python32.2 往自己的用户目录安装python31.首先下载安装包2.解压缩3.编译与安装 2.3 新建环境变量2.4 测试 3 创建PBS作业并提交 1.登录 windowsr打开运行命令窗口&#xff0c;在运行框中…

Springboot计算机课程教学辅助系统小程序【纯干货分享,免费领源码01616】

目 录 摘要 1 绪论 1.1课题背景 1.2研究现状 1.3springboot框架介绍 1.4小程序框架以及目录结构介绍 2 计算机课程教学辅助系统小程序系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统业务流程分析 2.3 系统功能…

SDN系统方法 | 10. SDN的未来

随着互联网和数据中心流量的爆炸式增长&#xff0c;SDN已经逐步取代静态路由交换设备成为构建网络的主流方式&#xff0c;本系列是免费电子书《Software-Defined Networks: A Systems Approach》的中文版&#xff0c;完整介绍了SDN的概念、原理、架构和实现方式。原文: Softwar…

记一次 .NET 某物流API系统 CPU爆高分析

一&#xff1a;背景 1. 讲故事 前段时间有位朋友找到我&#xff0c;说他程序CPU直接被打满了&#xff0c;让我帮忙看下怎么回事&#xff0c;截图如下&#xff1a; 看了下是两个相同的程序&#xff0c;既然被打满了那就抓一个 dump 看看到底咋回事。 二&#xff1a;为什么会打…

统信UOS安装Node.js v18环境

下载安装包 官网地址&#xff1a;Node.js 中文网 解压&#xff0c;-C指定解压的目录/usr/local/ sudo tar -xvf node-v18.17.0-linux-x64.tar.xz -C /usr/local/解压文件重命名 sudo mv /usr/local/node-v18.17.0-linux-x64 /usr/local/node加上软链接&#xff0c;将node源…

ACM图灵大会开幕,王海峰解读文心大模型3.5最新进展

7月28日-30日&#xff0c;顶级学术会议ACM中国图灵大会在武汉举办&#xff0c;围绕“通用智能&#xff0c;人机共生”主题&#xff0c;图灵奖得主、中国科学院院士、企业代表等与会探讨尖端技术及人工智能发展&#xff0c;展望计算科学未来。百度首席技术官、深度学习技术及应用…

Moving Average - 均线|技术分析基础

均线也只是一个跟随价格变化滞后于价格走势的工具&#xff0c;当你能够直接通过价格走势去获取信息&#xff0c;通过价格的走势去判断出行情的趋势&#xff0c;那你就不需要MA这个工具了。比如道氏理论对趋势的定义。高点不断创新高&#xff0c;低点不断抬升。通过对价格高低点…

quartus工具篇——fifo ip核

quartus工具篇——fifo ip核 1、简介 FPGA 中的 FIFO&#xff08;First-In, First-Out&#xff09;是一种常见的数据缓冲器&#xff0c;用于在不同的时钟域之间进行数据传输。FIFO 可以暂存一定数量的数据&#xff0c;并支持并行读取和写入操作&#xff0c;同时保持先进先出的…

立即报名 | AI +Serverless Meetup 上海站 8 月 5 日等你相约!

自 2021 年 5 月后&#xff0c;KubeSphere 社区与上海的各位小伙伴已阔别两年&#xff0c;许久不见&#xff0c;甚是想念&#xff01;2023 年 8 月 5 日&#xff0c;KubeSphere 社区将走进上海组织一场主题为 “AI Serverless” 的 Meetup。此外&#xff0c;云原生也依旧是本次…

AD21 PCB设计的高级应用(三)PCB多板互连装配设计

&#xff08;三&#xff09;PCB多板互连装配设计 一旦模块在多板原理图上相互连接,就可以验证板到板的连接。这将检测网络到引脚分配错误和引脚到引脚的互连布线错误。可以解决这些错误并将修改信息更新到对应的 PCB 中,或者重新更新到源系统原理图。 印制电路板不是孤立存在的…

【二进制转换】十进制 转 二进制 (含相关题型)

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 十进制 转 二进制 1. &运算符 介绍2. <…