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:…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
