android做一个简单的秒表功能遇到的问题

20200517
1、给按钮添加点击事件,实现开始和暂停的时候,我设定了一个isStarting的布尔型全局变量。然后在点击事件里面加了一个判断,当isStarting为false时,按钮为开始,然后启动一个线程每过1ms给Handler发送信息来刷新计时数据。开始我是直接创建一个线程,然后在点击事件里调用线程的start方法,想达到按下一次开始计时然后再按一下暂停,再按又能开始计时的效果。结果第二次想开始计时报错java.lang.IllegalThreadStateException,经网上查阅后得知,原来线程的生命周期是一个无法循环的过程,一个线程对象结束后不能再次start。所以我将Runnable里面的方法体分离出来,每次计时都会重新启动一个线程来执行方法。

2、处理时间遇到的问题。通过这次我才知道SimpleDateFormat对象的时间格式是可以精确到毫秒的,并且还有许多时间格式(具体看这里)。再然后Date是不能直接加减的,要先用getTime()方法再减,得到的是一个long类型。SimpleDateFormat对象的.format()方法也可以对这个long类型结果进行格式化。返回的是一个String类型。TextView组件的setText方法输出的是String类型,不能直接返回long类型的差值。

3、还有一个问题,最终做出来的秒表,在虚拟设备上运行一切正常,但是当我用自己的手机运行的时候,HH(小时)会莫名变成08。我输出开始时时间、结束时时间、还有差值都正常,但是计时的小时一栏就是会显示08,这个暂时没有解决,只好将HH去掉了。
20200518
因为我手机默认的时区是东八区,所以在格式化时间的时候系统会将时间差值当作零时区默认时间,然后以GMT+8来格式化它,所以会出现小时栏变成08的问题。将SimpleDateFormat对象的时区设为零时区就好了。即:simpleDateFormat.setTimeZone(TimeZone.getTimeZone(“GMT”)); 。然后虚拟设备的默认时区应该是GMT,所以没有问题。

20200525

先贴一个大佬的对线程的详细讲解博文

今天给秒表加了一个按钮,之前的那个按钮作为开始/清零,第二个按钮作为暂停/继续。在设置暂停功能时,发现在按钮点击时间里面调用相应线程的wait()会导致整个软件卡死。经大佬的博文得知原来只能在run方法里面调用wait()方法,不然会导致主线程阻塞,页面无响应。因此我加了一个isPause的boolean型全局变量,通过修改此变量的值来在run方法体里面判断是否wait()。再一个就是通过notify()方法再次启动线程(wait和notify调用时都必须加上锁(synchronized(){}),()里面是要执行的对象,不然会报错。),在调用时我开始是传了一个run方法体的当前执行线程作为操作对象进去,结果发现一直无法继续计时。后面将分离出来的线程任务的Runnable对象(即1里对handler发送信息的线程方法体对象)作为执行对象就能正常实现功能了。至于为什么是对实现方法体的Runnable对象执行操作而不是对执行方法的线程,这个暂时未知。如有大佬欢迎告知。
public class MainActivity extends AppCompatActivity {
private TextView time;
private Button button; //开始停止按钮
private Button button_2; //暂停继续按钮
private boolean isStarting = false;
private boolean isPause = false;
private Handler handler; //设置一个处理器
private Date startTime;
private Date currentTime;
private SimpleDateFormat sdf;
private long diff;
private Thread newThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    time = (TextView)findViewById(R.id.time);
    button = (Button)findViewById(R.id.button1);
    button_2 = (Button)findViewById(R.id.button2);

    time.setText("00:00:00:000");
    sdf = new SimpleDateFormat("HH:mm:ss:SSS"); //格式精确到毫秒
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));   //将时间格式设为零时区,不然小时一栏会变成08(GMT+8)。

    //消息处理器处理时间的显示
    handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(msg.what == 1){
                //加一层判断,不然最后一次接受消息时的计时会覆盖清零的显示效果。
                if (isStarting){
                    diff = currentTime.getTime() - startTime.getTime();
                    time.setText( sdf.format(diff) );
                }
            }
        }
    };

    //开始停止的点击时间
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(isStarting == false){
                startTime = new Date(System.currentTimeMillis());
                isStarting = true;
                newThread = new Thread(r);
                newThread.start();
                button.setText("Clear!");
            }else{
                isStarting = false;
                isPause = false;
                button_2.setText("Pause!");
                button.setText("Start!");
                time.setText("00:00:00:000");   //计时清零
            }
        }
    });

    //暂停继续的点击事件
    button_2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //判断计时是否已经开始
            if (isStarting){
                //判断是否暂停
                if (isPause == false){
                    isPause = true;
                    button_2.setText("Continue!");
                } else {
                    isPause = false;
                    //唤醒线程任务
                    synchronized (r){
                        r.notify();
                    }
                    button_2.setText("Pause!");
                }
            }
        }
    });
}

//设置一个线程任务,当isStarting = true时不断向向Handler发送信息更新计时
Runnable r = new Runnable() {           //因为线程不能重复启动,所以要将线程任务分离出来
    @Override
    public void run() {
        while(isStarting){
            //如果暂停就让线程wait
            while(isPause == true){
                synchronized (this){
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                break;
            }
            currentTime = new Date(System.currentTimeMillis());
            handler.sendEmptyMessage(1);
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
};

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值