Android5:活动生命周期
创建项目Stopwatch
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:gravity="center_horizontal"tools:context=".MainActivity"><Chronometerandroid:id="@+id/stopwatch"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="56sp" /><Buttonandroid:id="@+id/start_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/start" /><Buttonandroid:id="@+id/pause_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/pause" /><Buttonandroid:id="@+id/reset_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/reset" />
</LinearLayout>
strings.xml
<resources><string name="app_name">Stopwatch</string><string name="start">Start</string><string name="pause">Pause</string><string name="reset">Reset</string>
</resources>
MainActivity.kt
package com.demo.stopwatchimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.widget.Button
import android.widget.Chronometerclass MainActivity : AppCompatActivity() {lateinit var stopwatch: Chronometer //The stopwatchvar running = false //Is the stopwatch running?var offset: Long = 0 //The base offset for the stopwatchoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//Get a reference to the stopwatchstopwatch = findViewById<Chronometer>(R.id.stopwatch)//The start button starts the stopwatch if it's not runningval startButton = findViewById<Button>(R.id.start_button)startButton.setOnClickListener {if (!running) {setBaseTime()stopwatch.start()running = true}}//The pause button pauses the stopwatch if it’s runningval pauseButton = findViewById<Button>(R.id.pause_button)pauseButton.setOnClickListener {if (running) {saveOffset()stopwatch.stop()running = false}}//The reset button sets the offset and stopwatch to 0val resetButton = findViewById<Button>(R.id.reset_button)resetButton.setOnClickListener {offset = 0setBaseTime()}}//Update the stopwatch base time, allowing for any offsetfun setBaseTime() {stopwatch.base = SystemClock.elapsedRealtime() - offset}//Record the offsetfun saveOffset() {offset = SystemClock.elapsedRealtime() - stopwatch.base}
}
运行查看效果
代码说明
1.应用运行,MainActivity
启动
初始化running
和offset
属性
2.调用MainActivity
的onCreate
方法
将activity_main.xml
布局链接到活动,为stopwatch
属性指定视图的一个引用
3.点击“Start”按键
秒表开始运行
4.点击“Pause”按钮
更新offset
属性,并调用秒表的stop
方法,running
更新为false
,秒表暂停
5.再次点击“Start”按钮
使用offset
的值来调整stopwatch.base
属性,调用start
方法,更新running
为true
,表秒再次运行
6.点击“Reset”按钮
offset
更新为0,stopwatch.base
属性更新为SystemClock.elapsedRealtime()
但是这里有个问题,当旋转屏幕时,秒表会重置为0,并停止运行
旋转时发生了什么?
当屏幕方向有变化时,Android会撤销MainActivity
,所以MainActivity
的属性值会丢失
然后MainActivity
会重启,它的所有属性都会重新初始化,并且再次运行onCreate()
方法
活动从启动状态变成撤销状态时,会触发一些活动生命周期的方法:onCreate()
和onDestroy()
。这些是活动继承的生命周期方法,不过可以覆盖这些方法。
解决方案:使用Bundle
Bundle
是一种保存键值对的对象。在活动撤销之前,Android允许你把键值对放在Bundle里面,然后在活动重建时,活动的新实例通过Bundle
恢复属性值
活动撤销前都会调用onSaveInstanceState
方法,所以这里需要覆盖onSaveInstanceState
方法
活动重建时会调用onCreate()
方法,这里通过检查savedInstanceState != null
来判断是否需要恢复属性值
MainActivity.kt
最终代码
package com.demo.stopwatchimport androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.widget.Button
import android.widget.Chronometerclass MainActivity : AppCompatActivity() {lateinit var stopwatch: Chronometer //The stopwatchvar running = false //Is the stopwatch running?var offset: Long = 0 //The base offset for the stopwatch//Add key Strings for use with the Bundleval OFFSET_KEY = "offset"val RUNNING_KEY = "running"val BASE_KEY = "base"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//Get a reference to the stopwatchstopwatch = findViewById<Chronometer>(R.id.stopwatch)//Restore the previous stateif (savedInstanceState != null) {offset = savedInstanceState.getLong(OFFSET_KEY)running = savedInstanceState.getBoolean(RUNNING_KEY)if (running) {stopwatch.base = savedInstanceState.getLong(BASE_KEY)stopwatch.start()} else setBaseTime()}//The start button starts the stopwatch if it's not runningval startButton = findViewById<Button>(R.id.start_button)startButton.setOnClickListener {if (!running) {setBaseTime()stopwatch.start()running = true}}//The pause button pauses the stopwatch if it’s runningval pauseButton = findViewById<Button>(R.id.pause_button)pauseButton.setOnClickListener {if (running) {saveOffset()stopwatch.stop()running = false}}//The reset button sets the offset and stopwatch to 0val resetButton = findViewById<Button>(R.id.reset_button)resetButton.setOnClickListener {offset = 0setBaseTime()}}override fun onPause() {super.onPause()if (running) {saveOffset()stopwatch.stop()}}override fun onResume() {super.onResume()if (running) {setBaseTime()stopwatch.start()offset = 0}}override fun onSaveInstanceState(savedInstanceState: Bundle) {savedInstanceState.putLong(OFFSET_KEY, offset)savedInstanceState.putBoolean(RUNNING_KEY, running)savedInstanceState.putLong(BASE_KEY, stopwatch.base)super.onSaveInstanceState(savedInstanceState)}//Update the stopwatch base time, allowing for any offsetfun setBaseTime() {stopwatch.base = SystemClock.elapsedRealtime() - offset}//Record the offsetfun saveOffset() {offset = SystemClock.elapsedRealtime() - stopwatch.base}
}
相关文章:

Android5:活动生命周期
创建项目Stopwatch activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayoutxmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_w…...
第2章 数据结构和算法概述
2.3线性结构和非线性结构 数据结构包括: 线性结构和非线性结构 2.3.1线性结构 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系线性结构有两种不同的存储结构,即顺序存储结构(数组)和链式存储结构(链表)。顺序存储的线性表称…...

WPF国际化的实现方法(WpfExtensions.Xaml)
https://blog.csdn.net/eyupaopao/article/details/120090431 resx资源文件实现 resx资源文件,实现的过程比第一种复杂,但resx文件本身编辑比较简单,维护起来比较方便。需要用到的框架:WpfExtensions.Xaml 为每种语言添加.resx资…...

【Linux】—— 进程程序替换
目录 序言 (一)替换原理 1、进程角度——见见猪跑 1️⃣ 认识 execl 函数 2、程序角度——看图理解 (二)替换函数 1、命名理解 2、函数理解 1️⃣execlp 2️⃣execv 3️⃣execvp 4️⃣execle 5️⃣execve 6️⃣execve…...

idea创建javaweb项目,jboss下没有web application
看看下图这个地方有没有web application...

广东灯具3D扫描抄数建模服务3D测绘出图纸三维逆向设计-CASAIM
灯具三维逆向建模是一种将实际物体转换为数字模型的过程。通过逆向工程技术,可以将现有的灯具进行3D扫描,然后利用专业的逆向设计软件将其转换为准确的三维模型。 以下是CASAIM实施灯具三维逆向建模的一般步骤图: 1. 扫描:三维扫…...
Nginx反向代理-负载均衡、webshell实践
目录 1.nginx反向代理-负载均衡 1)搭建web项目 2)修改 nginx.conf的配置 2.webshell 实践 1)异或操作绕过 2)取反绕过 3)php语法绕过 1.nginx反向代理-负载均衡 1)搭建web项目 首先通过SpringBoo…...

第六阶|见道明心的笔墨(上)从书法之美到生活之美——林曦老师的线上直播书法课
如果你有需要,可以找我的,我这边有老师的所有课程 如果你有需要,可以找我的,我这边有老师的所有课程...
nbcio-boot从3.0升级到3.1的出现用户管理与数据字典bug
升级后出现 系统管理里的用户管理出现下面问题 2023-08-17 09:44:38.902 [http-nio-8080-exec-4] [1;31mERROR[0;39m [36mo.jeecg.common.exception.JeecgBootExceptionHandler:69[0;39m - java.lang.String cannot be cast to java.lang.Long java.lang.ClassCastException:…...

Curson 编辑器
Curson 汉化与vacode一样 Curson 自带chat功能 1、快捷键ctrlk(代码中编辑) 2、快捷键ctrll 右侧打开窗口...
Shell编程学习之函数的应用
Shell编程中的函数:伪代码表示: function 函数名(){函数体}注意事项: 1.函数无参数; 2.函数无返回值类型; 3.function可以不写; 4.函数不被调用,就不会执行; 5.函数名不能使用…...

Fork/Join框架
是什么 Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。 Fork: 把一个大任务切分为若干子任务并行的执行 Join: 合并这些子任务的执行结果,最后…...
LeetCode_字符串_中等_468.验证 IP 地址
目录 1.题目2.思路3.代码实现(Java) 1.题目 给定一个字符串 queryIP。如果是有效的 IPv4 地址,返回 “IPv4” ;如果是有效的 IPv6 地址,返回 “IPv6” ;如果不是上述类型的 IP 地址,返回 “Nei…...

ABAP Der Open SQL command is too big.
ABAP Der Open SQL command is too big. DBSQL_STMNT_TOO_LARGE CX_SY_OPEN_SQL_DB 应该是选择条件中 维护的条件值条数太多了...

QChart类用来 管理 图表的:数据序列(series)、图例(legend)和坐标轴(axis)
QChart类用来 管理 图表的:数据序列(series)、图例(legend)和坐标轴(axis) 1、数据序列类 继承关系 2、坐标轴类 的继承关系 3、图例类 什么是图例? 图例:是集中于地图…...
Servlet+JDBC实战开发书店项目讲解第10篇:在线客服功能实现
在线客服功能实现 实现思路 要实现在线客服功能,您可以考虑以下步骤: 创建一个用于存储客户消息和回复的数据库表。您可以使用JDBC连接到数据库,并使用SQL语句创建表格。 在您的Servlet中,创建一个用于处理客户消息和回复的POS…...

CVE-2023-21292 AMS框架层高危漏洞分析
文章目录 前言漏洞细节故事起源漏洞利用漏洞修复 总结 前言 本周在分析 Google 官方发布的 Android 2023 年8 月安全公告 涉及的漏洞补丁的时候,遇到一个有意思的漏洞:CVE-2023-21292。 之所以说它有意思是因为这个漏洞早在去年年底就在某平台上被国外…...
cuda、cuDNN、深度学习框架、pytorch、tentsorflow、keras这些概念之间的关系
当讨论CUDA、cuDNN、深度学习框架、pytorch、tensorflow、keras这些概念的时候,我们讨论的是与GPU加速深度学习相关的技术和工具。 CUDA(Compute Unified Device Architecture): CUDA是由NVIDIA开发的一种并行计算平台和编程模型&…...

第二讲:BeanFactory的实现
BeanFactory的实现 1. 环境准备2. 初始化DefaultListableBeanFactory3. 手动注册BeanDefinition4. 手动添加后置处理器5. 获取被依赖注入的Bean对象6. 让所有的单例bean初始化时加载7. 总结 Spring 的发展历史较为悠久,因此很多资料还在讲解它较旧的实现,…...

vue2+Spring Boot2.7 大文件分片上传
之前我们文章 手把手带大家实现 vue2Spring Boot2.7 文件上传功能 将了上传文件 但如果文件很大 就不太好处理了 按正常情况甚至因为超量而报错 这里 我弄了个足够大的文件 我们先搭建 Spring Boot2.7 环境 首先 application.yml 代码编写如下 server:port: 80 upload:path:…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...