在购物网站的促销活动中一般都有倒计时限制购物时间或者折扣的时间,这些都是如何实现的呢?
效果如图:
1、常用方法
方法一
Timer与TimerTask(Java实现)
public class timerTask extends Activity{ private int recLen = 11; private TextView txtView; Timer timer = new Timer(); public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.timertask); txtView = (TextView)findViewById(R.id.txttime); timer.schedule(task, 1000, 1000); // timeTask } TimerTask task = new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { // UI thread @Override public void run() { recLen--; txtView.setText(""+recLen); if(recLen < 0){ timer.cancel(); txtView.setVisibility(View.GONE); } } }); } }; }
public class timerTask extends Activity{ private int recLen = 11; private TextView txtView; Timer timer = new Timer(); public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.timertask); txtView = (TextView)findViewById(R.id.txttime); timer.schedule(task, 1000, 1000); // timeTask } final Handler handler = new Handler(){ @Override public void handleMessage(Message msg){ switch (msg.what) { case 1: txtView.setText(""+recLen); if(recLen < 0){ timer.cancel(); txtView.setVisibility(View.GONE); } } } }; TimerTask task = new TimerTask() { @Override public void run() { recLen--; Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; }
Handler与Message(不用TimerTask) public class timerTask extends Activity{ private int recLen = 11; private TextView txtView; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.timertask); txtView = (TextView)findViewById(R.id.txttime); Message message = handler.obtainMessage(1); // Message handler.sendMessageDelayed(message, 1000); } final Handler handler = new Handler(){ public void handleMessage(Message msg){ // handle message switch (msg.what) { case 1: recLen--; txtView.setText("" + recLen); if(recLen > 0){ Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 1000); // send message }else{ txtView.setVisibility(View.GONE); } } super.handleMessage(msg); } }; }
public class timerTask extends Activity{ private int recLen = 0; private TextView txtView; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.timertask); txtView = (TextView)findViewById(R.id.txttime); new Thread(new MyThread()).start(); // start thread } final Handler handler = new Handler(){ // handle public void handleMessage(Message msg){ switch (msg.what) { case 1: recLen++; txtView.setText("" + recLen); } super.handleMessage(msg); } }; public class MyThread implements Runnable{ // thread @Override public void run(){ while(true){ try{ Thread.sleep(1000); // sleep 1000ms Message message = new Message(); message.what = 1; handler.sendMessage(message); }catch (Exception e) { }
Handler与Runnable(最简单型) public class timerTask extends Activity{ private int recLen = 0; private TextView txtView; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.timertask); txtView = (TextView)findViewById(R.id.txttime); handler.postDelayed(runnable, 1000); } Handler handler = new Handler(); Runnable runnable = new Runnable() { @Override public void run() { recLen++; txtView.setText("" + recLen); handler.postDelayed(this, 1000); } }; }
上一篇讲到了计时的几种方法,在虚拟机中不会出现问题,但是在真机测试中,会遇到这样一种情况: 在手机进行休眠状态后,原来的睡60秒时间,大约变成了睡7分钟左右才再执行.这一直让我很不解,也没有发现代码上有什么问题.
后来发现别人也遇到了类似的问题. 发现常见的应用中,如游戏,播放器以及控制灯光显示中,都会有这种情况,
后来通过找了一个资料才知道如果要定时执行的话,要用AlarmManager,这是闹钟服务,Android手机中必须要保证AlarmManager的时钟跟真实时间同步的.所以在 Android手机休眠状态下,AlarmManager时间是不会变慢的. 以下介绍AlarmManager的基本使用.
2.1 AlarmManager简介及使用场景
AlarmManager的使用机制有的称呼为全局定时器,有的称呼为闹钟。通过对它的使用,它的作用和Timer有点相似。
都有两种相似的用法:
(1)在指定时长后执行某项操作
(2)周期性的执行某项操作
AlarmManager对象配合Intent使用,可以定时的开启一个Activity,发送一个BroadCast,或者开启一个Service.
当你的应用不在运行,而此时你仍然需要你的应用去执行一些操作(比如,短信拦截),只有这种时候才使用AlarmManager, 其他正常情况下的,推荐使用Handler。
AlarmManager 生命周期:repeating AlarmManager一旦启动就会一直在后台运行(除非执行cancel方法),可以在“应用管理”中看到这个应用状态是正在运行。 “强行停止”可以让Alarmmanager停掉。尝试了几种任务管理器, 都只能重置计数器(确实释放内存了),但都无法关闭定时器,只有系统自带的“强行停止”奏效。
如果某个AlarmManager已经启动, 程序又再次去启动它,只要PendingIntent是一样,那么之前那个AlarmManager会被release掉。
2.2 AlamManager具体方法及属性详解
AlarmManager 包含的主要方法:
// 取消已经注册的与参数匹配的定时器 void cancel(PendingIntent operation) //注册一个新的延迟定时器 void set(int type, long triggerAtTime, PendingIntent operation) //注册一个重复类型的定时器 void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation) //注册一个非精密的重复类型定时器 void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation) //设置时区 void setTimeZone(String timeZone)
public static final int ELAPSED_REALTIME // 当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是相对时间,是从系统启动后开始计时的,包括睡眠时 间,可以通过调用SystemClock.elapsedRealtime()获得。系统值是3 (0x00000003)。 public static final int ELAPSED_REALTIME_WAKEUP //能唤醒系统,用法同ELAPSED_REALTIME,系统值是2 (0x00000002) 。 public static final int RTC //当系统进入睡眠状态时,这种类型的闹铃不会唤醒系统。直到系统下次被唤醒才传递它,该闹铃所用的时间是绝对时间,所用时间是UTC时间,可以通过调用 System.currentTimeMillis()获得。系统值是1 (0x00000001) 。 public static final int RTC_WAKEUP //能唤醒系统,用法同RTC类型,系统值为 0 (0x00000000) 。 Public static final int POWER_OFF_WAKEUP //能唤醒系统,它是一种关机闹铃,就是说设备在关机状态下也可以唤醒系统,所以我们把它称之为关机闹铃。使用方法同RTC类型,系统值为4(0x00000004)。
使用AlarmManager共有三种方式, 都是通过PendingIntent。
getActivity(Context, int, Intent, int) getBroadcast(Context, int, Intent, int) getService(Context, int, Intent, int)
/* * Copyright (c) 2011, Yulong Information Technologies * All rights reserved. * * @Project: AlarmTest * @author: Robot */ package com.yfz; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; /** * @author Robot * @weibo [url]http://weibo.com/feng88724[/url] * @date Nov 18, 2011 */ public class ActionBroadCast extends BroadcastReceiver { private static int num = 0; /* (non-Javadoc) * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent) */ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.e("ActionBroadCast", "New Message !" + num++); } } now, 3000, pi); } }
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yfz" android:versionCode="1" android:versionName="1.0" > <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".AlarmTestActivity" > <receiver android:name="ActionBroadCast"> </receiver> </activity </application>