安卓实战项目 Sunny天气App

2023-11-04 05:50

本文主要是介绍安卓实战项目 Sunny天气App,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介:

学了一段时间的安卓了,最近准备跟着 第一行代码 这本书做一个较为完整的App项目,巩固一下所学到的知识。现在 第一行代码 这本书已经出到第三版了,里面是使用Kotlin进行开发的。但我平时还是Java用的比较多点,因此,我就想使用Java 来实现第三版中的 SunnyWeather 天气预报APP。下面就是关于这次项目的一些学习笔记。


1.准备工作

实现的功能和所需的技术要点都在书 P601页上有详细描述,这里就不再哆嗦了。在工作开始之前,先得按照书上描述,申请开放的天气API 接口,提交申请后,大概需要3~4个工作日才能通过审核。
如果之前使用的是第二版进行学习的同学,可能还需要了解一些第二版中没有提到的一些新内容。主要就是网络请求框架Retrofit、Jetpack中的ViewModel和LiveData 这些内容。

虽然安卓应用同时支持Java和Kotlin进行开发,但使用Kotlin代码编写的部分操作,在使用Java进行重写的时候,还是会出现一些问题,下面就是对出现的部分问题的一些说明。


2.问题说明

2.1 网络请求同步的问题

这是一个比较棘手的问题。到最后,我也没有能够完美解决。在实际开发中,我们常常需要发起网络请求,并将请求到的数据赋给一个实例,然后再进行一系列,如数据处理,UI更新等操作,但我在开发过程中,却遇到了 还没等到网络请求操作,程序就先进行数据操作 这种问题。
下面是项目中的具体例子,方便我们理解这个问题。(相关代码可见项目Repository类和SunnyNetWork类)

//获取到对应的数据模型类的实例,返回的数据不为null
final PlaceResponse placeResponse = sunnyWeatherNetwork.searchPlaces(query);
if (placeResponse.getStatus().equals("ok")) {places = placeResponse.getPlaces();// 获取到包含地区信息的listLog.d("Repository","place response success " );placesData.postValue(places);//将list传入Livedata内,并准备返回
} else {//返回状态不是ok的情况Log.d("Repository", "place status is" + placeResponse.getStatus() );
}

上面是项目中实现搜索地区数据信息功能的部分代码。首先, sunnnyWeatherNetwork .searchPlaces 这个方法中封装了网络请求操作以及空指针检测,返回获取到的数据并保证数据不为null。我们调用该方法,并把返回值赋给 placeResponse 。随后我们对placeResponse中的 status 值进行判断,如果为“ok”, 则进行一些数据处理操作,否则,则打印错误信息。
逻辑上来看,这段代码不难理解,而且在实现上应该没有什么问题。但实际上却存在空指针异常或是数据错误等问题。
下面是对项目进行调试时的记录日志:

调试记录
我们从上面的调试记录中可以看到,仓库层(Repository)已经进行完数据处理了,网络请求才完成。这样导致的后果就是取得的 placeResponse 为空或者为null。我自己思考的结论是,问题出现的原因是:进行网络请求时,Restrofit 会 new 一个线程,在另一个线程中进行网络请求,这样的结果就是仓库层的线程和网络请求线程并发执行,导致出现:没等网络请求成功响应,程序就进一步执行的情况。


解决方案:
在Kotlin中,我们可以使用async函数和await()方法,来实现同步。但我在用Java编写时,由于水平不足,没有很好地解决同步问题,因此会出现这样的问题:进行网络请求时,第一次网络请求得到的结果,是错误的,需要丢弃。

在搜索地区信息功能模块中,该问题导致搜索框体验不佳,需要在输入 想要搜索的地区信息后,再按下其他键。(等于发起第二次请求)才能搜索到结果。
输入北京后,需要在输入一个任意按键,才能正确显示结果
可以看到,输入北京后,还需要再输入任意一个按键,才能正确显示结果。

在天气信息显示功能中,为了解决这个问题,我就写了个循环,隔一小段时间就进行一次网络请求,直到返回的对象不为空时,再跳出循环。

do {//realtimeResponse 和 dailyResponse通过调用封装的网络请求方法获取realtimeResponse = sunnyWeatherNetwork.getRealtimeWeather(lng, lat);dailyResponse = sunnyWeatherNetwork.getDailyWeather(lng, lat);Log.d("Repository","refresh Weather 数据申请中");sleep(500);
}while (realtimeResponse == null || dailyResponse == null);//只有两个不为null时才跳出循环

这些方法只是暂时的解决,应该可以通过线程同步等方式的到更好的解决。

2.2 其他问题

1.项目中显示的文字均采用硬编码的写法。更合理的做法应该是定义在String.xml 中,然后在布局中引用。
2.编码不够规范。变量定义还不够规范(例如很多变量声明时未加上final),部分文档也没写清楚,代码自我感觉比较乱。
3.搜索界面中,状态栏与搜索框颜色不同,略显违和
4.部分机型兼容问题。在实现背景图与状态栏融合的效果时,在Android Studio 上的Pixel4上进行测试时,会发生图标折叠的情况。然而在实体机上,却不会出现这种情况。
在这里插入图片描述
5.天气api令牌值的引用存在问题。在PlaceService中可以通过代码 ${SunnyWeatherApplication.TOKEN} 来取得令牌值,但在WeatherService 中使用相同的引用方法,却提示令牌错误。最后我也没发现是什么原因导致的,只能在WeatherService中显式的填入令牌值才解决问题。


3.后续可扩展功能

1.修复上述提到的问题
2.实现后台更新天气信息
3.通过位置信息,自动选择城市
4.适配深色主题


4.源码链接

下面是这次实战项目的源码链接,希望能给有需要学习的同学提供一点帮助吧。

Sunny天气源码链接

这篇关于安卓实战项目 Sunny天气App的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/343661

相关文章

Nginx实现高并发的项目实践

《Nginx实现高并发的项目实践》本文主要介绍了Nginx实现高并发的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用最新稳定版本的Nginx合理配置工作进程(workers)配置工作进程连接数(worker_co

Spring AI与DeepSeek实战一之快速打造智能对话应用

《SpringAI与DeepSeek实战一之快速打造智能对话应用》本文详细介绍了如何通过SpringAI框架集成DeepSeek大模型,实现普通对话和流式对话功能,步骤包括申请API-KEY、项目搭... 目录一、概述二、申请DeepSeek的API-KEY三、项目搭建3.1. 开发环境要求3.2. mav

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Python与DeepSeek的深度融合实战

《Python与DeepSeek的深度融合实战》Python作为最受欢迎的编程语言之一,以其简洁易读的语法、丰富的库和广泛的应用场景,成为了无数开发者的首选,而DeepSeek,作为人工智能领域的新星... 目录一、python与DeepSeek的结合优势二、模型训练1. 数据准备2. 模型架构与参数设置3

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

Java使用Tesseract-OCR实战教程

《Java使用Tesseract-OCR实战教程》本文介绍了如何在Java中使用Tesseract-OCR进行文本提取,包括Tesseract-OCR的安装、中文训练库的配置、依赖库的引入以及具体的代... 目录Java使用Tesseract-OCRTesseract-OCR安装配置中文训练库引入依赖代码实

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内