Android实现倒计时

先上一个本人实际操作中的界面:

源代码:
(activity_main.xml和MainActivity.java)

activity_main.xml:

"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"    tools:context= ".MainActivity" >    id="@+id/inputtime"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:ems="10" >                

MainActivity.java:(第一次实现,推荐下面的优化实现)

package com.example.counttime;import java.util.Timer;import java.util.TimerTask;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.app.Activity;import android.content.DialogInterface;import android.view.View;import android.view.View.OnClickListener;import android.text.Editable;import android.view.Menu;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity2 extends Activity implements OnClickListener{        private EditText inputET ;        private Button getTime ,startTime ,stopTime ;        private TextView timeTV ;        private int i =0;//用作倒计时        private Timer timer =null;        private TimerTask timerTask =null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout. activity_main);        initView(); //首先进行初始化                                            }    private void initView(){       //初始化组件       inputET=(EditText) findViewById(R.id. inputtime);        timeTV=(TextView) findViewById(R.id. time);        getTime=(Button) findViewById(R.id. gettime);        startTime=(Button) findViewById(R.id.starttime);        stopTime=(Button) findViewById(R.id. stoptime);        //为按钮设置监听事件        getTime.setOnClickListener( this);        startTime.setOnClickListener(this);        stopTime.setOnClickListener( this);    }        @Override        public void onClick(View v) {               //为按钮添加监听事件               switch (v.getId()) {               case R.id.gettime :                     String t= inputET.getText().toString();                      timeTV.setText(t);                      i=Integer. parseInt(t);                      break;               case R.id.starttime :                     startTime();                      break;               case R.id.stoptime :                     stopTime();                      break;              }       }        private Handler mHandler =new Handler(){               public void handleMessage(Message msg){                      //更新主UI                      //String time=String.valueOf(msg.arg1);                      timeTV.setText(msg. arg1+ "");//TextView只能承载字符串类型的操作                     startTime();              }       };        public void startTime(){               timer= new Timer();               timerTask=new TimerTask() {                      @Override                      public void run() {                            i--;                           Message message= mHandler.obtainMessage();                           message. arg1= i;                            mHandler.sendMessage(message);                                       }              };              Toast. makeText(this, "点击了开始计时按钮",0);               //启动Timer(以秒为单位的倒计时)               timer .schedule(timerTask, 1000);       }        public void stopTime(){              Toast. makeText(this, "点击了停止计时按钮" ,0);               timer.cancel();       }}

MainActivity.java(优化实现):

package com.example.counttime;import java.util.Timer;import java.util.TimerTask;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.app.Activity;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener{        private EditText inputET ;        private Button getTime ,startTime ,stopTime ;        private TextView timeTV ;        private int i =0;//用作倒计时        private Timer timer =null;        private TimerTask timerTask =null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout. activity_main);        initView(); //首先进行初始化                                            }    private void initView(){       //初始化组件       inputET=(EditText) findViewById(R.id. inputtime);        timeTV=(TextView) findViewById(R.id. time);        getTime=(Button) findViewById(R.id. gettime);        startTime=(Button) findViewById(R.id.starttime);        stopTime=(Button) findViewById(R.id. stoptime);        //为按钮设置监听事件        getTime.setOnClickListener( this);        startTime.setOnClickListener(this);        stopTime.setOnClickListener( this);    }        @Override        public void onClick(View v) {               //为按钮添加监听事件               switch (v.getId()) {               case R.id.gettime :                     String t= inputET.getText().toString();                      timeTV.setText(t);                      i=Integer. parseInt(t);                      break;               case R.id.starttime :                     startTime();                      break;               case R.id.stoptime :                     stopTime();                      break;              }       }        private Handler mHandler =new Handler(){               public void handleMessage(Message msg){                      //更新主UI                      //String time=String.valueOf(msg.arg1);                      timeTV.setText(msg. arg1+ "");//TextView只能承载字符串类型的操作                     startTime();              }       };        public void startTime(){               timer= new Timer();               timerTask=new TimerTask() {                      @Override                      public void run() {                            i--;                           Message message= mHandler.obtainMessage();                           message. arg1= i;                            mHandler.sendMessage(message);                                       }              };              Toast. makeText(this, "点击了开始计时按钮",0);               //启动Timer(以秒为单位的倒计时)               timer .schedule(timerTask, 1000);       }        public void stopTime(){              Toast. makeText(this, "点击了停止计时按钮" ,0);               timer.cancel();       }}

开发中遇到的问题及知识点总结:

一、
view.post(runnableStartTime);
view.removeCallBacks(runnableStartTime);//终止一个线程

二、
textView.setText(“”);//清空一个文本框的值

三、Handler

1、Handler的定义:
主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 “强制关闭”. 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

2、Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行

Handler中分发消息的一些方法:

post(Runnable)postAtTime(Runnable,long)postDelayed(Runnable long)sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message,long)sendMessageDelayed(Message,long)

以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

3、Handler实例
(1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据
以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容

public class MyHandlerActivity extends Activity {    Button button;    MyHandler myHandler;    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.handlertest);        button = (Button) findViewById(R.id.button);        myHandler = new MyHandler();        // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据        // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象        // (2): 让一个动作,在不同的线程中执行.        // 它安排消息,用以下方法        // post(Runnable)        // postAtTime(Runnable,long)        // postDelayed(Runnable,long)        // sendEmptyMessage(int)        // sendMessage(Message);        // sendMessageAtTime(Message,long)        // sendMessageDelayed(Message,long)        // 以上方法以 post开头的允许你处理Runnable对象        //sendMessage()允许你处理Message对象(Message里可以包含数据,)        MyThread m = new MyThread();        new Thread(m).start();    }    /**    * 接受消息,处理消息 ,此Handler会与当前主线程一块运行    * */    class MyHandler extends Handler {        public MyHandler() {        }        public MyHandler(Looper L) {            super(L);        }        // 子类必须重写此方法,接受数据        @Override        public void handleMessage(Message msg) {            // TODO Auto-generated method stub            Log.d("MyHandler", "handleMessage......");            super.handleMessage(msg);            // 此处可以更新UI            Bundle b = msg.getData();            String color = b.getString("color");            MyHandlerActivity.this.button.append(color);        }    }    class MyThread implements Runnable {        public void run() {            try {                Thread.sleep(10000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }            Log.d("thread.......", "mThread........");            Message msg = new Message();            Bundle b = new Bundle();// 存放数据            b.putString("color", "我的");            msg.setData(b);            MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI        }    }}

四、Message

五、Timer和TimeTask

1、Timer和TimeTask简介

 java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。

一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。
Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程的能力。

2、Timer里面有4个schedule重载函数,而且还有两个scheduleAtFixedRate:

void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定速率执行。
void scheduleAtFixedRate(TimerTask task, long delay, long period)
安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
使用scheduleAtFixedRate的话,Timer会尽量的让任务在一个固定的频率下运行。例如:在上面的例子中,让secondTask在1秒钟后,每3秒钟执行一次,但是因为java不是实时的,所以,我们在上个程序中表达的原义并不能够严格执行,例如有时可能资源调度紧张4秒以后才执行下一次,有时候又3.5秒执行。如果我们调用的是scheduleAtFixedRate,那么Timer会尽量让你的secondTask执行的频率保持在3秒一次。运行上面的程序,假设使用的是scheduleAtFixedRate,那么下面的场景就是可能的:1秒钟后,secondTask执行一次,因为系统繁忙,之后的3.5秒后secondTask才得以执行第二次,然后Timer记下了这个延迟,并尝试在下一个任务的时候弥补这个延迟,那么2.5秒后,secondTask将执行的三次。“以固定的频率而不是固定的延迟时间去执行一个任务”就是这个意思。

3、Timer终止的问题:
默认情况下,只要一个程序的timer线程在运行,那么这个程序就会保持运行。可以通过以下3种方法终止一个timer线程:
(1)调用timer的cancle方法。你可以从程序的任何地方调用此方法,甚至在一个timer task的run方法里;
(2)让timer线程成为一个daemon线程(可以在创建timer时使用new Timer(true)达到这个目地),这样当程序只有daemon线程的时候,它就会自动终止运行;
(3)调用System.exit方法,使整个程序(所有线程)终止。
TimerTask也有cancel方法。
上面所说的“只要一个程序的timer线程在运行,那么这个程序就会保持运行”。那么反过来,如果Timer里的所有TimerTask都执行完了,整个程序会退出吗,经测试答案是否定的,例如上面的测试代码,如果只加第一个TimerTask在Timer中执行:
timer.schedule(new MyTask(1), 5000);// 5秒后启动任务
那么5秒以后,其实整个程序还是没有退出,Timer会等待垃圾回收的时候被回收掉然后程序会得以退出,但是多长时间呢?在TimerTask的run函数执行完以后加上System.gc();就可以了。

4、一个完整的Timer

ava.util.Timer timer = new java.util.Timer(true);// true 说明这个timer以daemon方式运行(优先级低,// 程序结束timer也自动结束),注意,javax.swing// 包中也有一个Timer类,如果import中用到swing包,// 要注意名字的冲突。TimerTask task = new TimerTask() {public void run() {... //每次需要执行的代码放到这里面。}};//以下是几种调度task的方法:timer.schedule(task, time);// time为Date类型:在指定时间执行一次。timer.schedule(task, firstTime, period);// firstTime为Date类型,period为long// 从firstTime时刻开始,每隔period毫秒执行一次。timer.schedule(task, delay)// delay 为long类型:从现在起过delay毫秒执行一次timer.schedule(task, delay, period)// delay为long,period为long:从现在起过delay毫秒以后,每隔period// 毫秒执行一次。

更多相关文章

  1. android手记之--广播接收者
  2. Android(安卓)ActionBar与ViewPager合用
  3. android Gridview生成程序快捷键的复杂方法
  4. 简叙 Activity 生命周期及android 返回按钮扑捉
  5. 在android下获取有线和无线IP地址的方法,经测试可用
  6. Android中在fragment A里面点击button跳转到fragment B实现方法
  7. framework——应用进程启动流程
  8. Android(安卓)几种图像特效处理的集锦

随机推荐

  1. android 被强制横屏,Activity重启问题解决
  2. Android(java)学习笔记94:关于广播接收者的
  3. Android中的异常处理 CrashHandler
  4. Android的Service总结
  5. Android(安卓)user defined service hand
  6. Android(安卓)AIDL 实例
  7. 看Android(安卓)應用框架原理與程式設計36
  8. Programming 3D games on Android(安卓)w
  9. No resource identifier found for attri
  10. android高效编程之使用本地变量