使用Handler创建一个Android秒表应用
本文所有代码都放在以下链接中:https://github.com/MADMAX110/Stopwatch
0、应用是一个有活动、布局和其他资源组成的集合。其中一个活动是应用的主活动。每个应用都有一个主活动,在文件AndroidManifest.xml中指定。
1、默认地,每个应用都在自己的进程中运行。这样有助于保证应用安全。
2、但是可以使用startActivity(intent)传入一个意图启动另一个应用中的活动。(Android系统知道设备上已安装的所有应用和它们的活动,可以使用意图启动适当的活动)。
3、需要启动一个活动时,Android会检查是否已经有一个进程在运行这个应用。(如果存在这样一个进程,Android就会在该进程中运行这个活动。如果不存在这样的进程,Android将创建一个进程)。
4、Android启动一个活动时,回调用它的onCreate()方法。(只要创建活动就会运行onCreate())。
下面通过来实现一个秒表应用,分析一下底层活动是如何工作的,应用通常会出什么问题,以及如何使用活动生命周期方法修正这些问题。秒表应用包括一个活动和一个布局。布局中有一个文本视图,显示已经过去了多少时间,另外还会显示一个Start(开始)按钮来启动秒表,一个Stop(停止)按钮停止秒表,还有一个Reset(重置)按钮可以将计时器重置为0。
创建新Android工程,应用名为Stopwatch,选择最低的SDK,如下图所示。
另外还需要一个名为StopwatchActivity的空活动和一个activity_stopwatch的布局。

工程目录如图所示:

更新strings.xml,添加以下三行代码:
<string name="start">Start</string><string name="stop">Stop</string><string name="reset">Reset</string>
更新秒表布局代码
下面是布局的XML,这里描述了一个用来显示计时器的文本视图,另外还有三个按钮。
activity_stopwatch.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:padding="16dp"tools:context=".StopwatchActivity"><TextViewandroid:id="@+id/time_view"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textAppearance="@android:style/TextAppearance.Large"android:textSize="56sp"/><Buttonandroid:id="@+id/start_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="20dp"android:onClick="onClickStart"android:text="@string/start"/><Buttonandroid:id="@+id/stop_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="8dp"android:onClick="onClickStop"android:text="@string/stop"/><Buttonandroid:id="@+id/reset_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="8dp"android:onClick="onClickReset"android:text="@string/reset"/>
</LinearLayout>
单击Start按钮时会调用onCLickStop方法,单击Reset按钮时会调用onClickReset方法,单击Stop按钮时会调用onCLickStop方法。
我们还将使用一个名为runTimer()方法更新秒表。runTimer()方法每秒运行一次代码,检查秒表是否还在运行,如果确实还在运行,则使秒数递增,并在文本视图中显示秒数。
我们将使用两个私有变量记录秒表的状态。这里使用一个名为seconds的int变量跟踪秒表开始运行以来过去了多少秒,另一个使用一个名为running的布尔变量记录秒表目前是否还在运行。
为此,将StopwatchActivity.java的内容替换为以下代码:
package com.hfad.stopwatch;import android.app.Activity;
import android.os.Bundle;
import android.view.View;public class StopwatchActivity extends Activity {private int seconds = 0;//记录已经过去的秒数private boolean running;//秒表是否正常运行@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_stopwatch);}//启动秒表public void onClickStart(View view) {running = true;}//停止秒表public void onClickStop(View view) {running = false;}//单击reset按钮时会调用这个方法public void onClickReset(View view) {running = false;seconds = 0;}
}
创建runTimer方法,runTimer方法要得到布局中文视图引用,将seconds变量的内容格式化为小时,分钟和秒,然后在文本视图中显示。如果running变量设置为true,能让seconds变量递增。
private void runTimer() {//得到文本视图final TextView timeView = (TextView) findViewById(R.id.time_view);int hours = seconds / 3600;int minutes = (seconds%3600)/60;int secs = seconds % 60;//设置显示格式String time = String.format(Locale.getDefault(), "%d:%02d%02d", hours, minutes, secs);//设置文本视图timeView.setText(time);if (running) {++seconds;}}
要让这个代码一直循环,每秒递增seconds变量,并更新文本视图。而且要以一种不阻塞Android主线程的方式来实现。在非Android的Java程序中,可以使用后天线程完成类似这样的任务。不过在Android世界里,只有Android主线程可以更新用户界面,如果其他线程试图这样做,就会得到一个异常。可以使用Handler来解决这个问题。
Handler(消息处理器)是一个Android类,可以用来调度要在将来某个时间点运行的代码,还可以用它来提交需要在其他线程(非Android主线程)中运行的代码,在这里我们需要使用Handler调度秒表代码,让它每秒运行一次。
使用Handler时,可以把你想要调度的代码包装在一个Runnable对象中,然后使用Handler post()和postDelayed()方法指定希望这个代码在什么时间运行。
post()方法提交的代码要尽可能快地运行(通常几乎是立即运行),post()方法有一个参数,这是一个类型为Runnable的对象。Android世界里的Runable对象与普通Java中的Runnable很类似,就是你想要运行的一个作业。可以把想要运行的代码放在Runable的run()方法,Handler会确保这个代码尽可能快地运行。下面给出这个方法:
final Handler handler = new Handler();
handler.post(Runable);
postDelayed()方法与post()方法类似,只不过这个方法用来提交要在将来运行地代码。下面给出这个方法。
final Handler handler = new Handler();
handler.postDelayed(Runnable, long);
下面给出完整的StopwatchActivity代码:
package com.hfad.stopwatch;import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.Locale;
import android.os.Handler;public class StopwatchActivity extends Activity {private int seconds = 0;//记录已经过去的秒数private boolean running;//秒表是否正常运行@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_stopwatch);runTimer();//使用单独的方法更新秒表。创建活动会调用这个方法}//启动秒表public void onClickStart(View view) {running = true;}//停止秒表public void onClickStop(View view) {running = false;}//单击reset按钮时会调用这个方法public void onClickReset(View view) {running = false;seconds = 0;}private void runTimer() {//得到文本视图final TextView timeView = (TextView) findViewById(R.id.time_view);//创建一个新地Handlerfinal Handler handler = new Handler();//调用post()方法,传入一个新的Runnable。post()方法会立即运行代码handler.post(new Runnable() {public void run() {int hours = seconds / 3600;int minutes = (seconds%3600)/60;int secs = seconds % 60;//设置显示格式String time = String.format(Locale.getDefault(), "%d:%02d%02d", hours, minutes, secs);//设置文本视图timeView.setText(time);if (running) {++seconds;}//在1000ms后再次提交并运行Runnable中的代码,会反复调用handler.postDelayed(this, 1000);}});}
}
至此,一个基本秒表应用到此全部结束。
ps:不能直接在onCreate中写一个循环更新计时器,onCreate必须在屏幕显示之前完成,如果包含一个无线循环,这个方法将无法结束。
相关文章:
使用Handler创建一个Android秒表应用
本文所有代码都放在以下链接中:https://github.com/MADMAX110/Stopwatch 0、应用是一个有活动、布局和其他资源组成的集合。其中一个活动是应用的主活动。每个应用都有一个主活动,在文件AndroidManifest.xml中指定。 1、默认地,每个应用都在…...
node-sass安装失败解决方法总结
node-sass 安装失败的原因 npm 安装 node-sass 依赖时,会从 github.com 上下载 .node 文件。由于国内网络环境的问题,这个下载时间可能会很长,甚至导致超时失败。 解决方法一:使用淘宝镜像源(推荐) npm …...
C++特殊类设计
文章目录 1.设计一个类,不能被拷贝2.设计一个类,只能在堆上创建对象3.设计一个类,只能在栈上创建对象4.设计一个类,不能被继承5.设计一个类,只能创建一个对象5.1 单例模式5.2 饿汉模式5.3 懒汉模式5.4 两种模式的析构函…...
常用的python gpu加速方法
在使用 PyCharm进行机器学习的时候,我们常常需要自己创建一些函数,这个过程中可能会浪费一些时间,在这里,我们为大家整理了一些常用的 Python加速方法,希望能给大家带来帮助。 在 Python中,我们经常需要创建…...
SpringCloud-Gateway
什么是网关? 网关是一个服务,是访问内部系统的唯一入口,提供内部服务的路由中转,额外还可以在此基础上提供如身份验证、监控、负载均衡、限流、降级与应用检测等功能。 Spring Cloud Gateway 与 Zuul 对比 zuul1.x与zuul2.x Zu…...
【C++ qt4】操作json学习笔记
本博文源于笔者在学习c qt4操作json文件,qt4不支持json,里面的函数是json.h与jsoncpp.cpp我已经附在文末,大家可复制重命名用,里面的案例可以自己拿来敲或者直接copy也行.,一定利用好目录拖动,不然很长。 文章目录 1.从…...
【牛客刷题专栏】0x25:JZ24 反转链表(C语言编程题)
前言 个人推荐在牛客网刷题(点击可以跳转),它登陆后会保存刷题记录进度,重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏:个人CSDN牛客刷题专栏。 题目来自:牛客/题库 / 在线编程 / 剑指offer: 目录 前言问…...
useEffect
useEffect 1.依赖项是什么?2.useEffect怎么知道依赖项数组发生了改变?3.依赖项的改变会导致无限渲染吗?4.使用 Object.is 来比较新/旧 state 是否相等,浅比较?5.为什么要用浅比较,而不用深比较呢࿱…...
如何利用splice()和slice()方法操作数组
如何利用splice()和slice()方法操作数组 前言splice()是什么,有什么用?怎么用?slice()是什么,有什么用?怎么用?splice和slice方法的区别小结 前言 splice&am…...
一文读懂ChatGPT(全文由ChatGPT撰写)
最近ChatGPT爆火,相信大家或多或少都听说过ChatGPT。到底ChatGPT是什么?有什么优缺点呢? 今天就由ChatGPT自己来给大家答疑解惑~ 全文文案来自ChatGPT! 01 ChatGPT是什么 ChatGPT是一种基于人工智能技术的自然语言处理系统&…...
如何提升应届生职场竞争力
引言 对于应届毕业生来说,进入职场是既令人兴奋又具有挑战性的。面对竞争激烈的就业市场,提高自身的职场竞争力对于应届生来说尤为重要。本文旨在为应届生提供有价值的见解和实用的策略,帮助他们提升职场竞争力,增加在就业市场中的…...
David Silver Lecture 5: Model-Free Control
1 Introduction 1.1 内容 上一章是对一个unknown MDP进行value function的预测,相当于policy evaluation。这一章是对unknown MDP找到一个最优的policy, optimise value function. 1.2 On and Off-Policy Learning On-policy learning learn on the…...
MySQL-----事务管理
文章目录 前言一、什么是事务二、为什么会出现事务三、事物的版本支持四、事物的提交方式五、事务常见的操作方式六、事务隔离级别如何理解隔离性1隔离级别查看与设置隔离性读未提交【Read Uncommitted】读提交【Read Committed】可重复读【Repeatable Read】串行化【serializa…...
chatGPT润色中英论文软件-文章修改润色器
chatGPT可以润色英文论文吗? ChatGPT可以润色英文论文,它具备自动纠错、自动完善语法和严格全面的语法、句法和内容结构检查等功能,可以对英文论文进行高质量的润色和优化。此外,ChatGPT还支持学术翻译润色、查重及语言改写等服务…...
MacOS下安装和配置Nginx
一、安装brew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"按回车后,根据提示操作:输入镜像序号 --> 输入Y,回车等待brew安装完成即可。 在终端输入brew -v后,会提示…...
采用UWB(超宽频)技术开发的java版智慧工厂定位系统源码
室内定位系统源码,采用UWB定位技术开发的智慧工厂定位系统源码 技术架构:单体服务 硬件(UWB定位基站、卡牌) 开发语言:java 开发工具:idea 、VS Code 前端框架:vue 后端框架:s…...
【2023华为OD笔试必会20题--C语言版】《04 日志采集系统》——数组
本专栏收录了华为OD 2022 Q4和2023Q1笔试题目,100分类别中的出现频率最高(至少出现100次)的20道,每篇文章包括原始题目 和 我亲自编写并在Visual Studio中运行成功的C语言代码。 仅供参考、启发使用,切不可照搬、照抄,查重倒是可以过,但后面的技术面试还是会暴露的。✨✨…...
MySQL数据库——MySQL修改存储过程(ALTER PROCEDURE)
在实际开发过程中,业务需求修改的情况时有发生,所以修改 MySQL 中的存储过程是不可避免的。 MySQL 中通过 ALTER PROCEDURE 语句来修改存储过程。下面将详细讲解修改存储过程的方法。 MySQL 中修改存储过程的语法格式如下: ALTER PROCEDURE…...
ASEMI代理ADV7125JSTZ330原装ADI车规级ADV7125JSTZ330
编辑:ll ASEMI代理ADV7125JSTZ330原装ADI车规级ADV7125JSTZ330 型号:ADV7125JSTZ330 品牌:ADI/亚德诺 封装:LQFP-48 批号:2023 引脚数量:48 工作温度:-40C~85C 安装类型:表面…...
86盒IP对讲一键报警器
86盒IP对讲一键报警器 86盒IP对讲一键报警器:革命性保障生命安全的利器! 随着科技的飞速发展,我们的生活变得越来越方便和智能化。而86盒IP对讲一键报警器更是在这种背景下应运而生。这款产品不仅无缝对接各种手机APP,也可以在智…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
