安卓实战项目 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

相关文章

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

Spring Boot项目中结合MyBatis实现MySQL的自动主从切换功能

《SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能》:本文主要介绍SpringBoot项目中结合MyBatis实现MySQL的自动主从切换功能,本文分步骤给大家介绍的... 目录原理解析1. mysql主从复制(Master-Slave Replication)2. 读写分离3.

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S