您的位置:首页 > Web前端

使用Sharepreference+Thread+Handler进行异步处理实现倒计时功能

2017-05-10 17:20 579 查看
之前我写了一篇博文是重写了Button实现在控件内部进行的倒计时功能,但是存在一定的局限,详情可以看之前的博文:

Android自定义TimeButton实现倒计时按钮》:http://blog.csdn.net/ssbby/article/details/69258672;

这篇博文主要使用Sharepreference+Thread+Handler进行异步处理实现倒计时功能,解决了长时间倒计时在APP退出或者其他状态下返回之后,无法继续倒计时或者倒计时开始点不准确的问题,具体思路如下:

(1)先确定倒计时时长,转化为自己所需的时间形式,即hh:mm(二十四小时制HH:mm)或者秒的形式显示倒计时,存为time,然后在本地创建一个Sharepreference文件来存储倒计时开始的时间点First_time(假设用户点击了倒计时控件,或者在调用了倒计时开始的回调方法(不由用户开始倒计时),也就是倒计时第一次开始的时间戳为First_time,假如用户退出当前界面,那么第二次进入界面的时间戳为second_time,倒计时重新开始的时间点就为我们之前预定的倒计时时间-(second_time-First_time);

(2)在第一步的Sharepreference轻量级存储的基础上,使用Thread+Handler进行异步处理实现倒计时功能,使用run()方法每秒发送一次带obj的请求,handler接收请求获取对应的obj,这里的obj就是倒计时的开始点,然后每执行一次,就执行time--的操作,然后handler接收后刷新对应控件上的显示文字即可;

(3)在开始的地方调用thread.start()即可。

这可以解决在app被用户主动kill的情况下重新打开也可以开始倒计时。

老规矩,上图:



主要的代码段如下:

1.在对应开始倒计时的地方使用Sharepreference存储:

public static SharedPreferences mSharedPreferences;
...
(这里是倒计时按钮的点击事件回调方法)
//获取小时
SimpleDateFormat hour = new SimpleDateFormat("HH");
String date1 = hour.format(new java.util.Date());
//获取分钟
SimpleDateFormat min = new SimpleDateFormat("mm");
String date2 = min.format(new java.util.Date());
//获取秒
SimpleDateFormat soc = new SimpleDateFormat("ss");
String date3 = soc.format(new java.util.Date());
//时间转换成秒的总和来计算
first_time = String.valueOf(Integer.parseInt(date1)*60
+ Integer.parseInt(date2)*60
+ Integer.parseInt(date3));
time1 = 299;(因为在run中执行了time1--,所以设置为299为了满足run开始的条件。。)
//保存数据到本地
SharePrefencesUtil.saveFirstTime(first_time,mContext);
...2.在第二次进入界面的时候更改time的值
public class CarDetialActivity extends Activity{
...
private int time1;//倒计时时间
private int cha;//时间差
private int first_time_i;
private String time_text;
private String first_time;//按下按钮的系统时间
private int second_time;//第二次进入的系统时间
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cardetial_acticity);
...
//对是否有点击倒计时进行判断
mSharedPreferences = mContext.getSharedPreferences("First_Time", Context.MODE_PRIVATE);
Log.e("First_Time",mSharedPreferences.getString("first_time",""));
if (mSharedPreferences.getString("first_time","").equals("")){
//修改按钮的可点击和背景
car_wait_button.setEnabled(true);
car_wait_button.setBackground(getResources().getDrawable(R.drawable.login_button_bg));
}else {
//获取小时
SimpleDateFormat hour = new SimpleDateFormat("HH");
String date1 = hour.format(new java.util.Date());
//获取分钟
SimpleDateFormat min = new SimpleDateFormat("mm");
String date2 = min.format(new java.util.Date());
//获取秒
SimpleDateFormat soc = new SimpleDateFormat("ss");
String date3 = soc.format(new java.util.Date());
//时间转换成秒的总和来计算
second_time = Integer.parseInt(date1)*60
+ Integer.parseInt(date2)*60
+ Integer.parseInt(date3);
first_time_i = Integer.parseInt(mSharedPreferences.getString("first_time",""));
if(second_time - first_time_i >= 300){
time1 = 300;
car_wait_button.setEnabled(true);
car_wait_button.setBackground(getResources().getDrawable(R.drawable.login_button_bg));
}else {
cha = second_time - first_time_i;
time1 = 300 - cha;
car_wait_button.setEnabled(false);
car_wait_button.setBackground(getResources().getDrawable(R.drawable.false_btn));
}
}
}3.使用 Thread+Handler进行异步处理实现倒计时功能
先新建一个handler如下:

private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch(msg.what){
//执行不同的操作,2为倒计时
case 1:
sendWaitRequest(duration,carPlaceId);
break;
case 2:
// 判断倒计时到和-1的时候结束
if (msg.obj.equals(0) || msg.obj.equals(-1)){
SharePrefencesUtil.delateFirstTime(mContext);
car_wait_button.setEnabled(true);
car_wait_button.setText("点我排队");
car_wait_button.setBackground(getResources().getDrawable(R.drawable.login_button_bg));
}else {
time_text = String.valueOf(msg.obj);
car_wait_button.setText(time_text + "秒后重新排队");
car_wait_button.setBackground(getResources().getDrawable(R.drawable.false_btn));
}

break;
}
}
};线程如下:
public class TimerThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(1000);// 线程暂停1秒,单位毫秒
Message message = new Message();
message.what = 2;
if (time1 >= 0 && time1 < 300){
time1--;
message.obj = time1;
handler.sendMessage(message);// 发送消息
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}我是在onCreate()中调用开始此线程
new Thread(new TimerThread()).start();//启动倒计时线程最后,在使用由于这个thread.stop()和thread.destory()因为安全问题被禁用,所以这里可能会出现线程多开的问题,我们只需要设置一个flag判断是否需要开始线程,并且在线程方法内run()下的while(true)设置为while(flag)即可,关于解决线程多开的问题,之后再写一篇博文来记录这个问题~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息