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:…...
 
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
 
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
 
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
 
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
