Android5:活动生命周期

创建项目Stopwatch

在这里插入图片描述
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns: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">

    <Chronometer
            android:id="@+id/stopwatch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="56sp" />

    <Button
            android:id="@+id/start_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/start" />

    <Button
            android:id="@+id/pause_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/pause" />

    <Button
            android: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.stopwatch

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.widget.Button
import android.widget.Chronometer

class MainActivity : AppCompatActivity() {

    lateinit var stopwatch: Chronometer  //The stopwatch
    var running = false  //Is the stopwatch running?
    var offset: Long = 0  //The base offset for the stopwatch

    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //Get a reference to the stopwatch
        stopwatch = findViewById<Chronometer>(R.id.stopwatch)

        //The start button starts the stopwatch if it's not running
        val 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 running
        val 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 0
        val resetButton = findViewById<Button>(R.id.reset_button)
        resetButton.setOnClickListener {
            offset = 0
            setBaseTime()
        }
    }
    

    //Update the stopwatch base time, allowing for any offset
    fun setBaseTime() {
        stopwatch.base = SystemClock.elapsedRealtime() - offset
    }

    //Record the offset
    fun saveOffset() {
        offset = SystemClock.elapsedRealtime() - stopwatch.base
    }
}

运行查看效果

代码说明
1.应用运行,MainActivity启动
初始化runningoffset属性
2.调用MainActivityonCreate方法
activity_main.xml布局链接到活动,为stopwatch属性指定视图的一个引用
3.点击“Start”按键
秒表开始运行
4.点击“Pause”按钮
更新offset属性,并调用秒表的stop方法,running更新为false,秒表暂停
5.再次点击“Start”按钮
使用offset的值来调整stopwatch.base属性,调用start方法,更新runningtrue,表秒再次运行
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.stopwatch

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.widget.Button
import android.widget.Chronometer

class MainActivity : AppCompatActivity() {

    lateinit var stopwatch: Chronometer  //The stopwatch
    var running = false  //Is the stopwatch running?
    var offset: Long = 0  //The base offset for the stopwatch

    //Add key Strings for use with the Bundle
    val 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 stopwatch
        stopwatch = findViewById<Chronometer>(R.id.stopwatch)

        //Restore the previous state
        if (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 running
        val 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 running
        val 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 0
        val resetButton = findViewById<Button>(R.id.reset_button)
        resetButton.setOnClickListener {
            offset = 0
            setBaseTime()
        }
    }

    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 offset
    fun setBaseTime() {
        stopwatch.base = SystemClock.elapsedRealtime() - offset
    }

    //Record the offset
    fun saveOffset() {
        offset = SystemClock.elapsedRealtime() - stopwatch.base
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/80720.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS-PyQt小案例

前言&#xff1a;目前还在学习ROS无人机框架中&#xff0c;&#xff0c;&#xff0c; 更多更新文章详见我的个人博客主页【前往】 ROS与PyQt5结合的小demo&#xff0c;用于学习如何设计一个界面&#xff0c;并与ROS中的Service和Topic结合&#xff0c;从而控制多个小乌龟的运动…

设计HTML5表单

HTML5基于Web Forms 2.0标准对HTML4表单进行全面升级&#xff0c;在保持简便、易用的基础上&#xff0c;新增了很多控件和属性&#xff0c;从而减轻了开发人员的负担。表单为访问者提供了与网站进行互动的途径&#xff0c;完整的表单一般由控件和脚本两部分组成。 1、认识HTML…

ansible的playbook剧本

playbook剧本 PlayBook1.playbooks 本身由以下各部分组成2.示例&#xff1a;3.运行playbook补充参数&#xff1a; 4.定义、引用变量5.指定远程主机sudo切换用户6.when条件判断7.迭代8.Templates 模块1.先准备一个以 .j2 为后缀的 template 模板文件&#xff0c;设置引用的变量2…

记录--webpack和vite原理

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 每次用vite创建项目秒建好&#xff0c;前几天用vue-cli创建了一个项目&#xff0c;足足等了我一分钟&#xff0c;那为什么用 vite 比 webpack 要快呢&#xff0c;这篇文章带你梳理清楚它们的原理…

Linux命令200例:clock的具体应用,设置系统的时钟时间、硬件时钟和定时器等相关信息

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

Atlas 元数据管理

Atlas 元数据管理 1.Atlas入门 1.1概述 元数据原理和治理功能&#xff0c;用以构建数据资产的目录。对这个资产进行分类和管理&#xff0c;形成数据字典。 提供围绕数据资产的协作功能。 表和表之间的血缘依赖 字段和字段之间的血缘依赖 1.2架构图 导入和导出&#xff1…

Educational Codeforces Round 62 (Rated for Div. 2) C. Playlist

一开始肯定要排个序&#xff0c;b相同时t大的在前边&#xff0c;不同时b大的在前面。 然后想最多只能选k个的限制&#xff0c;可以这样想&#xff0c;每次用到的b只能用已选到的最小的值&#xff0c;那可以把每个b都枚举一遍&#xff0c;然后每一次选时长最长的&#xff0c;且…

CCF C³ 走进百度:大模型与可持续生态发展

2023年8月10日&#xff0c;由CCF CTO Club发起的第22期C活动在百度北京总部进行&#xff0c;以“AI大语言模型技术与生态发展”主题&#xff0c;50余位企业界、学界专家、研究人员就此进行深入探讨。 CCF C走进百度 本次活动&#xff0c;CCF秘书长唐卫清与百度集团副总裁、深…

DeepSort:基于检测的目标跟踪的经典

本文来自公众号“AI大道理” DeepSORT在SORT的基础上引入了深度学习的特征表示和更强大的目标关联方式&#xff0c;有效地减少了身份切换的数量&#xff0c;缓解了重识别问题。 ​ 1、DeepSORT简介 DeepSORT的主要思想是将目标检测和目标跟踪两个任务相结合。 首先使用目标检…

Docker环境安装elasticsearch和kibana

一、安装elasticsearch 创建es-network&#xff0c;让es、kibana在同一个网段&#xff1a; docker network create --driverbridge --subnet192.168.1.10/24 es-network运行elasticsearch docker run -d \ --name elasticsearch \ # 容器名 --hostname elasticsearch # 主机…

综述:计算机视觉中的图像分割

一、说明 这篇文章是关于图像分割的探索&#xff0c;这是解决计算机视觉问题&#xff08;如对象检测、对象识别、图像编辑、医学图像分析、自动驾驶汽车等&#xff09;的重要步骤之一。让我们从介绍开始。 二、图像分割介绍 图像分割是计算机视觉中的一项基本任务&#xff0c;涉…

Maven基础之仓库、命令、插件机制

文章目录 Maven 仓库中央仓库和本地仓库中央仓库本地仓库 Maven 命令generate 命令compile 命令clean 命令test 命令package 命令install 命令 Maven 插件机制官方插件&#xff1a;Compile 插件Tomcat 7 插件 Maven 仓库 中央仓库和本地仓库 [✎] 简单一点说 中央仓库是一个网…

k8s基本概念、k8s对象、三个命令玩转所有的yaml写法、给vscode安装插件、kubectl和kubelet及自动补全

文章目录 1、K8S基本概念2、kubernetes Objects&#xff08;k8s对象&#xff09;2.1、定义2.2、对象的spec和status2.3、如何写任意资源的yaml&#xff08;以Pod为例&#xff09;2.4、pod的yaml文件2.5、k8s对象yaml的结构2.6、管理k8s对象2.7、对象名称2.8、名称空间2.9、标签…

图神经网络 day2 图的分类

图神经网络基础算法 1 GCN2 GraphSAGE2.1 采样&#xff1a;采样固定长度的邻居2.2 聚合2.3 GraphSAGE_minibatch2.4 GraphSAGE_embedding 3 GAT4. 图网络的分类4.1 递归图神经网络 RGNN4.2 图卷积神经网络GCN4.3 图注意力网络 GAT4.4 图自动编码 GAE4.5 图时空网络 GSTN4.6 图生…

机器人的运动范围

声明 该系列文章仅仅展示个人的解题思路和分析过程&#xff0c;并非一定是优质题解&#xff0c;重要的是通过分析和解决问题能让我们逐渐熟练和成长&#xff0c;从新手到大佬离不开一个磨练的过程&#xff0c;加油&#xff01; 原题链接 机器人的运动范围https://leetcode.c…

机器学习之数据集

目录 1、简介 2、可用数据集 3、scikit-learn数据集API 3.1、小数据集 3.2、大数据集 4、数据集使用 ⭐所属专栏&#xff1a;人工智能 文中提到的代码如有需要可以私信我发给你&#x1f60a; 1、简介 当谈论数据集时&#xff0c;通常是指在机器学习和数据分析中使用的一组…

SSM——用户、角色、权限操作

1. 数据库与表结构 1.1 用户表 1.1.1 用户表信息描述 users 1.1.2 sql语句 CREATE TABLE users( id varchar2(32) default SYS_GUID() PRIMARY KEY, email VARCHAR2(50) UNIQUE NOT NULL, username VARCHAR2(50), PASSWORD VARCHAR2(50), phoneNum VARCHAR2(20), STATUS INT…

PHP之Base64+php://filter绕过、disabled_function绕过

目录 一、Base64php://filter绕过 1.思路分析 2.实践验证 二、disabled_function绕过 一、Base64php://filter绕过 上课讲了这样一道题&#xff0c;一起来看下(以下代码适用于PHP7.x及以上&#xff0c;5的版本会报错) <?php function fun($var): bool{$blacklist …

大文本的全文检索方案附件索引

一、简介 Elasticsearch附件索引是需要插件支持的功能&#xff0c;它允许将文件内容附加到Elasticsearch文档中&#xff0c;并对这些附件内容进行全文检索。本文将带你了解索引附件的原理和使用方法&#xff0c;并通过一个实际示例来说明如何在Elasticsearch中索引和检索文件附…

API开放!将语聚AI智能助手接入到您的自有系统中

概述 语聚AI基于集简云强大的应用软件“连接器”能力&#xff0c;提供了工具延展、知识延展、模型延展和嵌入集成等一系列功能&#xff0c;为用户带来了更加强大和智能的AI新体验。 我们深知&#xff0c;每家企业对于AI应用都有自己独特的需求和应用场景&#xff0c;只有通过开…