【Android实验】线程的使用-计时器
实验目的
熟悉和掌握Android线程的使用
实验要求
- 完成一个秒表,具备启停功能,正确使用工作线程完成界面刷新
 - 分析秒表的计时是否准确,原因是什么,如何保证秒表计时准确?
 
实验过程
实验结果

实验代码
界面部分
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="秒表"
        android:textAlignment="center"
        android:textSize="40dp"
        />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="00:00:00"
            android:id="@+id/tv_time"
            android:textAlignment="center"
            android:textSize="60dp"/>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
                <Space
                    android:layout_width="120dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    />
            <Button
                android:id="@+id/btn_clear"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="清零"
                android:textColor="#000000"
                android:textSize="25dp"
                android:background="#99FFFF"/>
            <Button
                android:id="@+id/btn_start"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="计时"
                 android:layout_weight="1"
                 android:textSize="25dp"
                android:background="#FFC8B4"
                />
            <Button
                 android:id="@+id/btn_stop"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="停止"
                 android:layout_weight="1"
                 android:textSize="25dp"
                android:background="#CCFF99"
                />
        </LinearLayout>
</LinearLayout>
核心代码
Timer.java
package com.example.administrator.exp5;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class Timer extends AppCompatActivity {
    private static Handler handler = new Handler();
    private static TextView tv_time = null;
    private static Button btn_clear,btn_start,btn_stop;
    private static String time;
    private int min=0,sec=0,psec= 0;
    boolean runflag = true;
    int status = 0; // 0 - clear ; 1 - start ; 2 - stop
    long last,templast = -1;
    String str="";
    private Thread workThread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv_time = (TextView)findViewById(R.id.tv_time);
        btn_clear = (Button)findViewById(R.id.btn_clear);
        btn_start = (Button)findViewById(R.id.btn_start);
        btn_stop = (Button)findViewById(R.id.btn_stop);
        workThread = new Thread(null,RefreshLabel,"workThread");
        workThread.start();
        last = System.currentTimeMillis();
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //计时开始
                status = 1;
                if(templast != -1)
                {
                    last = templast;
                }
            }
        });
        btn_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //停止计时
                status = 2;
                templast = last;
            }
        });
        btn_clear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                min = sec = psec = 0;
                //清零
                status = 0;
                last = System.currentTimeMillis();
                tv_time.setText("00:00:00");
                templast = -1;
            }
        });
    }
    private Runnable RefreshLabel = new Runnable() {
        @Override
        public void run() {
            try{
                while(runflag)
                {
                    Thread.sleep(50);
                    if(status == 1)
                    {
                        int t=0;
                        long tmp = System.currentTimeMillis();
                        long cha = tmp - last;
                        t = (int)cha/1000;
                        psec = (int)cha - t * 1000;
                        psec %= 100;
                        sec = t - ((int)t/60)*60;
                        min = (int)t/60;
                        if(min == 60)
                        {
                            min = 0;
                        }
                        str = "";
                        str = str + String.format("%02d",min) + ":" +String.format("%02d",sec) + ":" + String.format("%02d",psec);
                        tv_time.post(new Runnable() {
                            @Override
                            public void run() {
                                tv_time.setText(str);
                            }
                        });
                    }
                }
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    };
}
设计思路
    秒表需要完成停启功能,也就是说需要能够停下来,而且在停下来以后需要能够继续计时。这个计时的工作需要交付给一个子进程来做,每隔一段时间就刷新一次界面,从而达到计时的效果。
    如何使秒表计时更加准确?可以通过sleep(1000)来计时,或者采取不断访问系统时间的方式来计时。两种方式相比较,第二种方式更加准确,第一种解决方案由于sleep时间是人为设定的,跟手机的性能有一定关系,除此之外,由于程序间断性执行,这些时间也会计算到总时间中,所以第一种方案计时不准确。应该采用第二种计时方式。
实验总结
本实验主要是练习线程的使用,线程需要实现\(Runnable\)借口,并重载\(run()\)函数,在该函数中写入秒表运行的代码,进行计算:
private Runnable RefreshLabel = new Runnable(){
    @Override
    public void run(){
        try{
        }
        catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}
然后创建Thread对象,将Runnable对象作为参数传递给Thread对象。
private Thread workThread;
workThread = new Thread(null,RefreshLabel,"workThread")
需要的三个参数,第一个参数表示线程组,第二个参数是需要执行的Runnable对象,第三个参数是参数名称。
关于时间计算:
通过System.currentTimeMillis()函数返回当前计算机的时间所对应的毫秒数。
时间换算如下:
1min = 60s
1s = 1000ms
时间计算部分代码:
long tmp = System.currentTimeMillis();
long cha = tmp - last;
t = (int)cha/1000;
psec = (int)cha - t * 1000;
psec %= 100;
sec = t - ((int)t/60)*60;
min = (int)t/60;
if(min == 60)
{
	min = 0;
}
str = "";
str = str + String.format("%02d",min) + ":" +String.format("%02d",sec) + ":" + String.format("%02d",psec);
另外,由于单线程中,不能再UI线程外访问Android UI 工具包,则调用\(View.post()\)方法,进行异步通信。实现界面的动态更新。
【Android实验】线程的使用-计时器的更多相关文章
- android操作线程各种方法解析
		
(一)刚开始学习android的时候我是这么写的 new Thread( new Runnable() { public void run() { myView.invalidate(); } }). ...
 - Android UI线程和非UI线程
		
Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...
 - android 进程/线程管理(一)----消息机制的框架
		
一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统, ...
 - Android子线程真的不能更新UI么
		
Android单线程模型是这样描述的: Android UI操作并不是线程安全的,并且这些操作必须在UI线程执行 如果在其它线程访问UI线程,Android提供了以下的方式: Activity.run ...
 - android 进程/线程管理(二)----关于线程的迷思
		
一:进程和线程的由来 进程是计算机科技发展的过程的产物. 最早计算机发明出来,是为了解决数学计算而发明的.每解决一个问题,就要打纸带,也就是打点. 后来人们发现可以批量的设置命令,由计算机读取这些命令 ...
 - android 进程/线程管理(三)----Thread,Looper / HandlerThread / IntentService
		
Thread,Looper的组合是非常常见的组合方式. Looper可以是和线程绑定的,或者是main looper的一个引用. 下面看看具体app层的使用. 首先定义thread: package ...
 - android 进程/线程管理(四)续----消息机制的思考(自定义消息机制)
		
继续分析handler 和looper 先看看handler的 public void dispatchMessage(Message msg) { if (msg.callback != null) ...
 - android 进程/线程管理(四)----消息机制的思考(自定义消息机制)
		
关于android消息机制 已经写了3篇文章了,想要结束这个系列,总觉得少了点什么? 于是我就在想,android为什么要这个设计消息机制,使用消息机制是现在操作系统基本都会有的特点. 可是andro ...
 - Android子线程更新UI的方法总结
		
版权声明:本文为博主原创文章,转载请注明出处:https://i.cnblogs.com/EditPosts.aspx?postid=6121280 消息机制,对于Android开发者来说,应该是非常 ...
 - 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池
		
第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...
 
随机推荐
- JVM学习笔记-内存管理
			
第一章 内存分配 1. 内存区域. 方法区和堆(线程共享),程序计数器 , VM栈 和 本地方法栈(线程隔离). 1) java虚拟机栈:线程私有.描写叙述的是java方法执行的内存模 ...
 - MySQL Innodb日志机制深入分析
			
MySQL Innodb日志机制深入分析 http://blog.csdn.net/yunhua_lee/article/details/6567869 1.1. Log & Checkpoi ...
 - spring boot 使用静态资源
			
./ 当前目录../ 父级目录/ 根目录 spring boot 打包时: The default includes are as follows: 默认包括的文件 public/**, resour ...
 - [vue]实现父子组件数据双向绑定
			
参考: http://www.cnblogs.com/xxcanghai/p/6124699.html <!DOCTYPE html> <html lang="en&quo ...
 - [py]GIL(全局解释器锁):多线程模式
			
在多线程 时同一时刻只允许一个线程来访问CPU,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL 参考 Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务.多个P ...
 - Python自动发邮件-yagmail库
			
之前写过用标准库使用Python Smtplib和email发送邮件,感觉很繁琐,久了不用之后便忘记了.前几天看知乎哪些Python库让你相见恨晚?,看到了yagmail第三方库,学习过程中遇到一些问 ...
 - 1025 PAT Ranking[排序][一般]
			
1025 PAT Ranking (25)(25 分) Programming Ability Test (PAT) is organized by the College of Computer S ...
 - Android常用权限permission列表摘录
			
一个Android应用程序需要权限才能调用某些android系统的功能:一个android应用也可能被其他应用调用,因此也需要声明调用自身所需要的权限.除了平时常用的权限记得比较熟悉,还有很多的权限一 ...
 - Linux系统——MySQL基础(三)
			
### MySQL主从复制实践#### 主从复制实践准备(1)主从复制数据库实战环境准备MySQL主从复制实践对环境的要求比较简单,可以是单机单数据库多实例的环境,也可以是两台服务器,每个机器一个独立 ...
 - rpm服务的独立服务管理
			
/etc/init.d 启动脚本的位置 /etc/sysconfig/ 初始化环境配置文件 /etc/ 配置文件位置 /etc/xinetd.conf xinetd配置文件 /etc/xine ...