Android中利用Handler做的倒计时

时间:2021-08-05 10:16:23

此篇博客是根据github倒计时源码做的源码分析,github地址 https://github.com/android-cjj/Timer
下面先上效果图

Android中利用Handler做的倒计时
主要功能就是上边那四个小功能,还是比较全的。
下面是布局文件大家都看得懂不用多说了
上边helloworld是用来显示剩余时间的,下边的helloworld 1其实就是一个点击时间用来设置时间(这个后文再说先说定时功能)

xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"

android:layout_height="match_parent"android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:paddingBottom="@dimen/activity_vertical_margin"

tools:context=".MainActivity">

android:padding="20dp"

android:gravity="center"

android:id="@+id/text1"

android:text="hello_world"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

android:id="@+id/start"

android:layout_below="@+id/text1"

android:text="开始倒计时"

android:onClick="onClick"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

android:layout_below="@+id/start"

android:id="@+id/pause"

android:text="暂停倒计时"

android:onClick="onClick"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

android:id="@+id/resume"

android:layout_below="@+id/pause"

android:text="恢复倒计时"

android:onClick="onClick"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

android:id="@+id/cancel"

android:layout_below="@+id/resume"

android:text="移除倒计时"

android:onClick="onClick"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

android:gravity="center"

android:id="@+id/text2"

android:text="hello1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="onClick"

android:layout_below="@+id/cancel"

android:layout_alignParentStart="true"

android:layout_marginTop="24dp"/>

下面贴一下定时功能的java文件

b>1.实例化后必须设置倒计时的总时间(totalTime)和每隔多久时间(intervalTime)回调</b><br>
* <b>2.有start()、 cancel()、 pause()、resume() 四个方法看方法就知道它的意思了 </b>
*/
public class DownTimer {
private long totalTime = -1;//总时间
private long intervalTime = 0;//隔断时间
private long remainTime;//剩余时间
private long systemAddTotalTime;//系统开机时间加上总时间
private static final int TIME = 1;//message.what字段
private TimeListener listener;
private long curReminTime;//剩余时间,用来保存remainTime
private boolean isPause = false;

public DownTimer() {
}

public void setIntervalTime(long intervalTime) {
this.intervalTime = intervalTime;
}

public void setTotalTime(long totalTime) {
this.totalTime = totalTime;
}

public long getIntervalTime() {
return intervalTime;
}

public long getTotalTime() {
return totalTime;
}

public void start() {
if (totalTime <= 0 && intervalTime <= 0) {
throw new RuntimeException("you must set the totalTime > 0 or intervalTime >0");
//如果总的定时时间还有间隔时间都小于等于0的话就会报异常
}

systemAddTotalTime = SystemClock.elapsedRealtime() + totalTime;
//SystemClock.elapsedRealtime()是用来调用系统开机时间
//注意systemAddTotalTime这个是个定值,是指此时的开机时间加上定时时间因为是先定义这个变量然后再调用mHandler如果在handler里边定义的话就不是定值了

if (null != mHandler)
mHandler.sendEmptyMessage(TIME);
//如果mHandler不为空handler给message发送time字段进而执行计时功能
}

public void cancel() {
if(mHandler !=null)
{
mHandler.removeMessages(TIME);
//停止计时,handler就没有了计时功能
}

}

public void pause() {
if(mHandler !=null)
{
mHandler.removeMessages(TIME);//取消定时
isPause = true;//定义一个标志
curReminTime = remainTime;//记录剩余时间
}

}

public void resume() {
if (isPause == true) {
isPause = false;
totalTime = curReminTime;//重新定义定时时间
start();//恢复计时
}

}

private Handler mHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TIME:
if (!isPause)//isPausee为假的话就可以执行soloveTime();
soloveTime();
break;
case 2:
isPause = true;
break;
default:
break;
}
}
};


private void soloveTime() {
remainTime = systemAddTotalTime - SystemClock.elapsedRealtime();
//上边定义的定值减去此时的开机时间。remainTime这个值一直在变化。
if (remainTime <= 0) {//如果剩余时间小于0调用listener取消定时你可以在listener.onFinish()里边定义一些你想要的
if (listener != null) {
listener.onFinish();
cancel();
}
} else if (remainTime < intervalTime) {//如果剩余时间小于回调时间
if (null != mHandler)
mHandler.sendEmptyMessageDelayed(TIME, remainTime);//改变延时时间
} else {
//long curSystemTime = SystemClock.elapsedRealtime();
if (listener != null) {
listener.onInterval(remainTime);
}
//排除以上情况下的处理方法
long delay = intervalTime;//设置延时时间
//long delay = curSystemTime + intervalTime - SystemClock.elapsedRealtime();

//while (delay < 0) delay += intervalTime;

if (null != mHandler) {
mHandler.sendEmptyMessageDelayed(TIME, delay);
//用这个方法来回回调soloveTime();并且是延时发送message;
}
}
}

public interface TimeListener {
public void onFinish();
public void onInterval(long remainTime);
}

public void setTimerLiener(TimeListener listener) {

this.listener = listener;
}

}

代码有点多哈,别着急慢慢分析,在讲解代码前先要弄清原理,首先就是handler的原理此处借用《第一行代码》里面的讲解,

Android中利用Handler做的倒计时
这里简单说一下原理,如果不明白的自行百度谷歌Handler,Message会携带少量的信息进入looper无限循环,进而传给handler进行处理,然后handler又会传信息给message如此反复。这个循环一直在运行,只要message有信息handler就会根据message.what字段调用相应的方法。
代码分析已经写在备注里,此处需要注意的是sendEmptyMessageDelayed()方法,这个方法大家可以查阅资料达到的效果就是延时调用sendmessaage(Time)延时时间就是delay。
差点忘了activity这里边代码比较简单没什么可说的就是调用方法

 public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private DownTimer timer;
private TimePickerView pvTime;
private TextView text2;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv_scend = (TextView) findViewById(R.id.text1);
text2 = (TextView) findViewById(R.id.text2);
tv_scend.setText("总共三分钟");
timer = new DownTimer();//实例化
timer.setTotalTime(3*60*1000);//设置毫秒数
timer.setIntervalTime(60*1000);//设置间隔数
timer.setTimerLiener(new DownTimer.TimeListener() {
@Override
public void onFinish() {
Toast.makeText(MainActivity.this, "完成倒计时", Toast.LENGTH_SHORT).show();
tv_scend.setText("点击设置时间");
}

@Override
public void onInterval(long remainTime) {
tv_scend.setText("还剩" + remainTime / 1000/60+"分钟就完成了");//剩余多少秒
}
});

}

@Override
public void onClick(View v) {
switch (v.getId())
{
case R.id.start:
timer.start();
break;
case R.id.pause:
timer.pause();
break;
case R.id.cancel:
timer.cancel();
break;
case R.id.resume:
timer.resume();
break;
case R.id.text2:
choose();
break;
}
}

源码下载请看作者
https://github.com/android-cjj/Timer
另外还有一个就是如何做一个漂亮的时间选择器不是手动输入定时时间我给大家推荐一个不错的开源项目
这个不光有日期选择还有时间选择仔细阅读他的readmetxt就好了改一下模式就行,和定时功能结合更加哦!

Android中利用Handler做的倒计时

源码下载https://github.com/saiwu-bigkoo/Android-PickerView
还有就是给大家推荐项目集锦,里面很多好的开源项目
https://github.com/Trinea/android-open-project#%E5%8D%81timeview