kotlin 编写一个简单的天气预报app(一)

news2024/10/10 12:24:20

使用Android Studio开发天气预报APP

今天我来分享一下如何使用Android Studio开发一个天气预报APP。在文中,我们将使用第三方接口获取实时天气数据,并显示在APP界面上。

步骤一:创建新项目

首先,打开Android Studio并创建一个新的项目。在创建新项目时,我们需要设置项目名称、包名和支持的最低API级别。
在这里插入图片描述

步骤二:

为了获取实时天气数据,我们需要导入一个名为"Retrofit"的第三方库。可以使用以下代码在build.gradle文件中添加Retrofit库的依赖。

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
//network
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

步骤三:获取API Key

为了使用OpenWeatherMap API,您需要注册一个免费的API Key。请访问OpenWeatherMap官网进行注册,并获取API Key。
在这里插入图片描述

步骤四:创建接口

首先,我们需要创建一个接口,定义我们需要的网络请求方法。在这个例子中,我们需要一个根据城市名称获取天气信息的方法:

interface WeatherService {

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

步骤五:构建对应的数据结构

这是对应的WeatherRespone数据结构,用来序列化返回的json接口。
这个json结构可以从openweathermap的api里查看到:
在这里插入图片描述
返回值在这里
在这里插入图片描述
根据OpenWeatherMap API的响应格式,我们需要创建相应的数据模型。这里我们以WeatherResponse为例,创建对应的数据模型类,对应的kotlin结构体:


data class WeatherResponse(
    @SerializedName("coord")
    var coord: Coord? = null,
    @SerializedName("weather")
    var weather : ArrayList<Weather>,
    @SerializedName("base")
    var base: String? = null,
    @SerializedName("main")
    var main: Main? = null,
    @SerializedName("visibility")
    var visibility: Int = 0,
    @SerializedName("wind")
    var wind: Wind ?= null,
    @SerializedName("clouds")
    var clouds: Clouds ? = null,
    @SerializedName("dt")
    val dt: Int,
    @SerializedName("sys")
    var sys: Sys ? = null,
    @SerializedName("id")
    var id: Int = 0,
    @SerializedName("name")
    var name: String ?= null,
    @SerializedName("cod")
    var cod: Int
)

class Coord {
    @SerializedName("lon")
    var lon : Float = 0.toFloat()
    @SerializedName("lat")
    var lat : Float = 0.toFloat()
}

class Weather {
    @SerializedName("id")
    var id: Int = 0
    @SerializedName("main")
    var main: String ?= null
    @SerializedName("description")
    var description: String ?= null
    @SerializedName("icon")
    var icon: String ?= null
}

class Main {
    @SerializedName("temp")
    var temp: Float = 0.toFloat()
    @SerializedName("pressure")
    var pressure: Int = 0
    @SerializedName("humidity")
    var humidity: Int = 0
    @SerializedName("temp_min")
    var temp_min: Float = 0.toFloat()
    @SerializedName("temp_max")
    var temp_max: Float = 0.toFloat()
}

class Wind {
    @SerializedName("speed")
    var speed: Float = 0.toFloat()
    @SerializedName("deg")
    var deg: Int = 0
}

class Clouds {
    @SerializedName("clouds")
    var clouds: Int = 0
}

class Sys {
    @SerializedName("type")
    var type: Int = 0
    @SerializedName("id")
    var id: Int = 0
    @SerializedName("message")
    var message: Float = 0.toFloat()
    @SerializedName("country")
    var country: String ?= null
    @SerializedName("sunrise")
    var sunrise: Int = 0
    @SerializedName("sunset")
    var sunset: Int = 0
}

步骤六:创建Retrofit实例

接下来,我们需要创建一个Retrofit实例,并配置相关参数。在这个例子中,我们需要配置基础URL和Gson转换器:
调用getWeatherByCityName(“London”)来获取伦敦的天气情况

object RetrofitClient {
    private const val BASE_URL = "https://api.openweathermap.org/data/2.5/"
    private const val API_KEY = "add your api key"

    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    private val weatherService: WeatherService by lazy { retrofit.create(WeatherService::class.java) }

    fun getWeatherByCityName(cityName: String) {
        val call = weatherService.getWeatherByCityName(cityName, API_KEY)
        call.enqueue(object : Callback<WeatherResponse> {
            override fun onResponse(
                call: Call<WeatherResponse>,
                response: Response<WeatherResponse>
            ) {
                if (response.isSuccessful) {
                    val weatherData = response.body()
                    handleWeatherData(weatherData)
                } else {
                    handleWeatherFailure(response.message())
                }
            }

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

    private fun handleWeatherData(weatherData: WeatherResponse?) {
        if (weatherData != null) {
            println("coord: lat:${weatherData.coord?.lat},lon:${weatherData.coord?.lon}")
            for(weather in weatherData.weather) {
                println("weather: id:${weather.id},main${weather.main}," +
                        "description:${weather.description},icon:${weather.icon}")
            }
            println("base:${weatherData.base}")
            println("main: temperature:${weatherData.main?.temp},pressure:${weatherData.main?.pressure}," +
                    "humidity:${weatherData.main?.humidity},temperature_min:${weatherData.main?.temp_min}," +
                    "temperature_max:${weatherData.main?.temp_max}")
            println("visibility:${weatherData.visibility}")
            println("wind: speed:${weatherData.wind?.speed},deq:${weatherData.wind?.deg}")
            println("clouds: clouds:${weatherData.clouds?.clouds}")
            println("dt: ${weatherData.dt}")
            println("sys: type:${weatherData.sys?.type},id:${weatherData.sys?.id},message:${weatherData.sys?.message}" +
                    ",country:${weatherData.sys?.country},+sunrise:${weatherData.sys?.sunrise},+sunset:${weatherData.sys?.sunset}")
            println("id: ${weatherData.id}")
            println("name: ${weatherData.name}")
            println("cod: ${weatherData.cod}")
        }
    }

    private fun handleWeatherFailure(message: String) {
        println("Request failed: $message")
    }
}

步骤七:程序的运行结果:

W/ample.myweathe: Accessing hidden method Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/os/Trace;->traceCounter(JLjava/lang/String;I)V (light greylist, reflection)
I/System.out: coord: lat:51.5085,lon:-0.1257
I/System.out: weather: id:804,mainClouds,description:overcast clouds,icon:04n
I/System.out: base:stations
I/System.out: main: temperature:285.53,pressure:1007,humidity:91,temperature_min:284.02,temperature_max:286.53
I/System.out: visibility:10000
I/System.out: wind: speed:0.82,deq:347
I/System.out: clouds: clouds:0
I/System.out: dt: 1690252945
I/System.out: sys: type:2,id:2075535,message:0.0,country:GB,+sunrise:1690258398,+sunset:1690315226
I/System.out: id: 2643743
I/System.out: name: London
I/System.out: cod: 200
W/ample.myweathe: Accessing hidden method Landroid/graphics/FontFamily;-><init>()V (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/graphics/FontFamily;->freeze()Z (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/graphics/FontFamily;->abortCreation()V (light greylist, reflection)
W/ample.myweathe: Accessing hidden method Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface; (light greylist, reflection)

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

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

相关文章

Flutter 最佳实践和编码准则

Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则&#xff0c;可以提高代码质量、可读性和可靠性。它们确保遵循行业标准&#xff0c;鼓励一致性&#xff0c;并促进开发人员之间的合作。通过遵循最佳实践&#xff0c;代码变得更容易理解、修改和调试&#xff…

【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码(一)

系列文章 【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何训…

新能源电动车充电桩控制主板的技术

新能源电动车充电桩控制主板的技术 你是否曾经遇到过电动车行驶到一半没电的情况?这不仅尴尬&#xff0c;还可能对你的生活造成困扰。然而&#xff0c;随着充电桩主板技术的出现&#xff0c;这个问题得到了有效的解决。那么&#xff0c;这个技术到底包括哪些方面呢?让我们一起…

IDEA代码自动格式化工具

1.自动import 在IDEA中&#xff0c;打开 IDEA 的设置&#xff0c;找到 Editor -> General -> Auto Import。勾选上 Add unambiguous imports on the flyOptimize imports on the fly (for current project) 2.gitee 提交格式化 设置方法如下: 1.打开设置 2.找到版本…

如何写好测试报告?

目录 一、目标 二、模板的使用 三、修订记录 四、内容应该清晰易懂&#xff0c;简明扼要 五、绝不放过一个错字 六、遗留问题单 七、产出成果恰当呈现 一、目标 本文介绍测试人员编写软件测试报告常见的疏漏&#xff0c;以便大家避免&#xff0c;更好让测试成果呈现给客…

Kotlin 协程 CoroutineScope

协程定义&#xff1a; 19年官方是这样说的&#xff1a;协程是轻量级的线程&#xff0c;协程就是 Kotlin 提供的一套线程封装的 API&#xff1b; 现在官方是这样说的&#xff1a;协程是一种并发设计模式&#xff1b; 协程作用&#xff1a; 1.处理耗时任务&#xff1b; 2.保…

【雕爷学编程】Arduino动手做(172)---WeMos D1开发板模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

RL 实践(4)—— 二维滚球环境【DQN Double DQN Dueling DQN】

本文介绍如何用 DQN 及它的两个改进 Double DQN & Dueling DQN 解二维滚球问题&#xff0c;这个环境可以看做 gym Maze2d 的简单版本参考&#xff1a;《动手学强化学习》完整代码下载&#xff1a;5_[Gym Custom] RollingBall (DQN and Double DQN and Dueling DQN) 文章目录…

智能喷涂机器人的制作分享

作者&#xff1a;朱家谊、吾丽江、管孝天 单位&#xff1a;天津工业大学 指导老师&#xff1a;李鹏 1. 概念说明 智能喷涂机器人是一种具有自主感知、决策和执行能力的机器人&#xff0c;专门用于自动化喷涂任务&#xff0c;它可以应用于各种领域&#xff0c;如汽车制造、建…

【已解决】jupyter notebook里已经安装了第三方库,还是提示导入失败

在jupyter notebook中运行Python代码&#xff0c;明明已经安装了第三方库&#xff0c;还是提示导入失败。 以导入pandas库为例&#xff0c;其他库同理&#xff1a; 报错代码&#xff1a; import pandas报错原因&#xff1a; 电脑上存在多个python运行环境&#xff08;比如&a…

JavaScript学习 -- Hex编码

Hex编码是一种十六进制数字的表示方式。在JavaScript中&#xff0c;我们可以使用Hex编码来表示数字、颜色和其他二进制数据&#xff0c;并将其用于各种场景&#xff0c;例如Web开发、图像处理和加密解密等。在本篇博客中&#xff0c;我们将介绍Hex编码的基础知识和相关技术&…

Xilinx FPGA平台GTX简易使用教程(汇总篇)

GTX简易使用教程&#xff0c;先“知其然”&#xff0c;慢慢再研究“所以然”。 目录 一、GTX必备基础知识 二、时钟篇 三、复位与初始化 四、GTX IP核配置介绍 五、GTX收发测试 六、后记 一、GTX必备基础知识 虽说搬砖只需要会用IP就行&#xff0c;但是为了把砖搬好&a…

js:浏览器环境下复制图片到剪切板

浏览器环境下复制图片到剪切板思路&#xff1a; 通过canvas将图片url转为base64格式将base64格式转为Blob类型的数据调用浏览器接口复制内容到剪切板 图片处理工具方法 image-util.js // Image对象转base64 export function imageToBase64(image) {let canvas document.cr…

Canal深入调研

Canal深入调研 1.canal的设计 1.1 Canal的设计理念 canal的组件化设计非常好&#xff0c;有点类似于tomcat的设计。使用组合设计&#xff0c;依赖倒置&#xff0c;面向接口的设计。 说明&#xff1a; ​ server代表一个canal运行实例&#xff0c;对应于一个jvm ​ instance…

免费分享一套基于SpringBoot实现商城系统(仿天猫),挺漂亮的

大家好&#xff0c;我是锋哥&#xff0c;看到一个不错的基于SpringBoot实现商城系统(仿天猫)系统&#xff0c;分享下哈。 项目介绍 迷你天猫商城是一个基于Spring Boot的综合性B2C电商平台&#xff0c;需求设计主要参考天猫商城的购物流程&#xff1a;用户从注册开始&#xf…

编码器原理

编码器原理 编码器是一种用来测量机械旋转或位移的传感器。这种传感器能够测量机械部件在旋转或直线运动时的位移位置或速度等信息,并将其转换成一系列电信号。 光栅式旋转编码器 霍尔式编码器

制作一个简易的计算器app

1、Ui开发 笔者的Ui制作的制作的比较麻烦仅供参考&#xff0c;在这里使用了多个LinearLayout对屏幕进行了划分。不建议大家这样做最好使用GridLayout会更加快捷简单 笔者大致划分是这样的&#xff1a; 使用了四个大框&#xff0c;在第四个大框里面有多个小框 最终界面如下&am…

Linux(一)

一.FinalShell远程连接Linux系统&#xff08;可能在自己电脑虚拟机上也可能在服务器上&#xff09; 二.掌握使用WSL获得Ubuntu系统环境 WSL作为Windows10系统带来的全新特性。 传统方式获取Linux操作系统环境&#xff0c;是安装完整的虚拟机&#xff0c;如VMware 使用WSL&#…

系统架构设计师 10:软件架构的演化和维护

一、软件架构演化 如果软件架构的定义是 SA{components, connectors, constraints}&#xff0c;也就是说&#xff0c;软件架构包括组件、连接件和约束三大要素&#xff0c;这类软件架构演化主要关注的就是组件、连接件和约束的添加、修改与删除等。 二、面向对象软件架构演化…

点云分割-pcl区域生长算法

目录 写在前面原理代码运行结果 参考完 写在前面 1、本文内容 pcl的区域生长算法的使用和原理 2、平台/环境 cmake, pcl 3、转载请注明出处&#xff1a; https://blog.csdn.net/qq_41102371/article/details/131927376 原理 参考&#xff1a;https://pcl.readthedocs.io/pr…