??開發(fā)中經(jīng)常遇到用計(jì)時器的時候,例如:每秒輸出一次log,這時候就要用到延時操作,這里總結(jié)了幾種常用的方法。
十余年品牌的成都網(wǎng)站建設(shè)公司,超過千家企業(yè)網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn).價格合理,可準(zhǔn)確把握網(wǎng)頁設(shè)計(jì)訴求.提供定制網(wǎng)站建設(shè)、購物商城網(wǎng)站建設(shè)、微信小程序、響應(yīng)式網(wǎng)站開發(fā)等服務(wù),我們設(shè)計(jì)的作品屢獲殊榮,是您值得信賴的專業(yè)網(wǎng)站設(shè)計(jì)公司。
?? AlarmManager 是Android的全局定時器,可以在指定時間執(zhí)行定時任務(wù)。定時任務(wù)通過PendingIntent 的 getActivity()、getService()或 getBroadcast() 來執(zhí)行。簡單的說就是我們設(shè)定一個時間,然后在該時間到來時,AlarmManager為我們廣播一個我們設(shè)定的Intent出來,在接收到設(shè)定的Intent時執(zhí)行定時任務(wù)。
(2) setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法用于設(shè)置重復(fù)鬧鐘,其中參數(shù)說明如下:
type:鬧鐘類型
startTime:首次執(zhí)行鬧鐘的時間
intervalTime:兩次執(zhí)行鬧鐘的時間間隔
pi:鬧鐘響應(yīng)動作
(3) setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法也用于設(shè)置重復(fù)鬧鐘,與第二個方法相似,區(qū)別在于其兩次鬧鐘執(zhí)行的間隔時間不是固定的。
?? AlarmManager實(shí)現(xiàn)定時的方法,我還沒有用到過,以上內(nèi)容是在網(wǎng)上查找資料后自己在一個小demo中小小試驗(yàn)了的,有錯誤或描述不清的地方請見諒。下面是我參考的介紹AlarmManager的三篇文章。
類似iOS中的NSTimer 定時器功能,開關(guān)控制隨機(jī)幾秒鐘執(zhí)行指定功能;
平臺:Android
開發(fā)環(huán)境:android Studio
代碼實(shí)現(xiàn):
一. 創(chuàng)建Handler對象和Runnable對象
[java] view plain copy print?
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
if (mPageOpen){
if (interstitialAd.isLoaded()){ //示例-谷歌插頁廣告
interstitialAd.show();
}else {
AdRequest adRequest = new AdRequest.Builder().build();
interstitialAd.loadAd(adRequest);
}
int random = (int)(Math.random() * 10 +20)*1000; //隨機(jī)時間循環(huán)執(zhí)行
handler.postDelayed(this, random);
}
}
};
二. 開關(guān)控制
[java] view plain copy print?
Switch mSwith = (Switch) findViewById(R.id.switchPage);
mSwith.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mPageOpen = true;
} else {
mPageOpen = false;
}
handler.postDelayed(runnable, 15000); //開關(guān)控制執(zhí)行
}
});
三. 移除定時器
[java] view plain copy print?
handler.removeCallbacks(runnable);
不會。安卓實(shí)現(xiàn)同時多個倒計(jì)時效果的步驟:
1、首先需要在輸入框中輸入一個秒數(shù),比如:12,然后獲取輸入框中的值,顯示在一個TextView中;
2、點(diǎn)擊“開始倒計(jì)時”按鈕,每隔一秒鐘,秒數(shù)減1,然后顯示在TextView中;
3、點(diǎn)擊“停止倒計(jì)時”按鈕,計(jì)時器停止運(yùn)行,當(dāng)再次點(diǎn)擊“開始倒計(jì)時”按鈕,計(jì)時器繼續(xù)運(yùn)行。
4、平時用的每個商品都應(yīng)該有兩個屬性值,這里叫它deadLine和isOverdue吧,表示商品的到期時間和是否到期,那么倒計(jì)時可以考慮這么實(shí)現(xiàn):設(shè)置一個主計(jì)時器,每隔1秒發(fā)出消息告訴GridView現(xiàn)在的時間,GridView的Item獲得這個時間之后就和deadLine比較,如果已經(jīng)到deadline了,就把數(shù)據(jù)源中的這項(xiàng)標(biāo)記成已到期(修改isOverdue的值為true);沒到deadline,就計(jì)算還差多少時間,顯示到GridView的Item里。
android計(jì)時器,時間計(jì)算器的實(shí)現(xiàn)方法,需要的朋友可以參考一下
需求:默認(rèn)為"00:00:00",點(diǎn)擊開始按鈕時清零后開始計(jì)時,出現(xiàn)如10:28:34。點(diǎn)擊停止的時候停止計(jì)時。
問題:使用Calendar
DateFormat的方法,不設(shè)置時區(qū)獲取到的小時是本地時區(qū)的(東八區(qū)的就是8),設(shè)置成GMT標(biāo)準(zhǔn)時區(qū)獲取到的時間是12小時(12:00:00),設(shè)置24小時制無效。
在開始時間加減各種小時都無效,而且計(jì)時只能到12小時就自動跳上去了,始終無法出現(xiàn)默認(rèn)狀態(tài)00:00:00開始計(jì)時的效果。
嘗試各種時間設(shè)置方法無效后只能自己寫一個根據(jù)秒數(shù)轉(zhuǎn)換時間格式字符串的方法了,經(jīng)過測試是沒問題的,兩位數(shù)只能顯示99小時為最大,如需要更大小時數(shù)需要改改方法。
另外小時數(shù)也不能無限大,超過long數(shù)據(jù)類型長度會變成負(fù)數(shù)的,會出現(xiàn)異常的。
顯示效果:
測試類:
復(fù)制代碼
代碼如下:
public class TestTime {
public
static void main(String[] args) {
TestTime tt = new
TestTime();
tt.showTimeCount(99*3600000+75*1000);
}
//時間計(jì)數(shù)器,最多只能到99小時,如需要更大小時數(shù)需要改改方法
public String
showTimeCount(long time) {
System.out.println("time="+time);
if(time =
360000000){
return "00:00:00";
}
String
timeCount = "";
long hourc = time/3600000;
String hour =
"0" + hourc;
System.out.println("hour="+hour);
hour =
hour.substring(hour.length()-2, hour.length());
System.out.println("hour2="+hour);
long minuec =
(time-hourc*3600000)/(60000);
String minue = "0" +
minuec;
System.out.println("minue="+minue);
minue =
minue.substring(minue.length()-2, minue.length());
System.out.println("minue2="+minue);
long secc =
(time-hourc*3600000-minuec*60000)/1000;
String sec = "0" +
secc;
System.out.println("sec="+sec);
sec =
sec.substring(sec.length()-2, sec.length());
System.out.println("sec2="+sec);
timeCount = hour + ":" + minue +
":" + sec;
System.out.println("timeCount="+timeCount);
return timeCount;
}
}
實(shí)際例子:
復(fù)制代碼
代碼如下:
//時間計(jì)數(shù)器,最多只能到99小時,如需要更大小時數(shù)需要改改方法
public String showTimeCount(long time) {
if(time =
360000000){
return "00:00:00";
}
String
timeCount = "";
long hourc = time/3600000;
String hour =
"0" + hourc;
hour = hour.substring(hour.length()-2,
hour.length());
long minuec =
(time-hourc*3600000)/(60000);
String minue = "0" +
minuec;
minue = minue.substring(minue.length()-2,
minue.length());
long secc =
(time-hourc*3600000-minuec*60000)/1000;
String sec = "0" +
secc;
sec = sec.substring(sec.length()-2, sec.length());
timeCount = hour + ":" + minue + ":" + sec;
return
timeCount;
}
private Handler stepTimeHandler;
private Runnable mTicker;
long startTime = 0;
//開始按鈕
class startBtnListener implements OnClickListener {
@Override
public void onClick(View v) {
Button b =
(Button)v;
String buttonText =
b.getText().toString();
if("Start".equalsIgnoreCase(buttonText)){
b.setText("Stop");
// 清零 開始計(jì)時
stepTimeTV.setText("00:00:00");
stepTimeHandler = new
Handler();
startTime =
System.currentTimeMillis();
mTicker = new Runnable()
{
public void run() {
String
content = showTimeCount(System.currentTimeMillis() -
startTime);
stepTimeTV.setText(content);
long now =
SystemClock.uptimeMillis();
long next = now + (1000
- now % 1000);
stepTimeHandler.postAtTime(mTicker,
next);
}
};
//啟動計(jì)時線程,定時更新
mTicker.run();
}else{
b.setText("Start");
//停止計(jì)時 Remove
any pending posts of Runnable r that are in the message
queue.
stepTimeHandler.removeCallbacks(mTicker);
}
}
}
用時間格式化的方式測試代碼:
復(fù)制代碼
代碼如下:
//開始按鈕 通過Calendar時間設(shè)置的方式,無法正常顯示小時為0
class startBtnListener implements OnClickListener {
@Override
public void onClick(View v) {
Button b =
(Button)v;
String buttonText =
b.getText().toString();
if("Start".equalsIgnoreCase(buttonText)){
b.setText("Stop");
// 清零 開始計(jì)時
stepTimeTV.setText("00:00:00");
if (mCalendar == null)
{
mCalendar =
Calendar.getInstance();
TimeZone tz =
TimeZone.getTimeZone("GMT");//GMT+8
mCalendar.setTimeZone(tz);
mCalendar.get(Calendar.HOUR_OF_DAY);//24小時制
}
stepTimeHandler = new Handler();
//System.uptimeMillis()
//記錄從機(jī)器啟動后到現(xiàn)在的毫秒數(shù),當(dāng)系統(tǒng)進(jìn)入深度睡眠時,此計(jì)時器將會停止
//System.currentTimeMillis()
//返回自1970年1月1日到現(xiàn)在的毫秒數(shù),通常用來設(shè)置日期和時間
//System.elapsedRealtime()
//返回從機(jī)器啟動后到現(xiàn)在的毫秒數(shù),包括系統(tǒng)深度睡眠的時間,api里沒有這個方法
//直接取得的是當(dāng)?shù)貢r區(qū)時間,當(dāng)?shù)貢r間跟時區(qū)有關(guān),設(shè)置GMT后始終多12小時
startTime =
System.currentTimeMillis();//12*3600000 - 36*3600000減掉或者加上12小時都不行
mTicker = new Runnable() {
public
void run() {
//這個減出來的日期是1970年的 時間格式不能出現(xiàn)00:00:00
12:00:00
long showTime = System.currentTimeMillis()
- startTime;
Log.i(TAG,showTime+"");
mCalendar.setTimeInMillis(showTime + 13*3600000 +
1000);
String content = (String)
DateFormat.format(mFormat, mCalendar);
stepTimeTV.setText(content);
long now =
SystemClock.uptimeMillis();
long next = now + (1000
- now % 1000);
stepTimeHandler.postAtTime(mTicker,
next);
}
};
//啟動計(jì)時線程,定時更新
mTicker.run();
}else{
b.setText("Start");
//停止計(jì)時 Remove
any pending posts of Runnable r that are in the message
queue.
stepTimeHandler.removeCallbacks(mTicker);
}
}
}
private Handler stepTimeHandler;
Calendar
mCalendar;
String mFormat = "yyyy-MM-dd hh:mm:ss";//yyyy-MM-dd
long startTime = 0;
private Runnable mTicker;
安卓實(shí)現(xiàn)同時多個倒計(jì)時效果的步驟:
我們首先需要在輸入框中輸入一個秒數(shù),比如:12,然后獲取輸入框中的值,顯示在一個TextView中;
點(diǎn)擊“開始倒計(jì)時”按鈕,每隔一秒鐘,秒數(shù)減1,然后顯示在TextView中;
點(diǎn)擊“停止倒計(jì)時”按鈕,計(jì)時器停止運(yùn)行,當(dāng)再次點(diǎn)擊“開始倒計(jì)時”按鈕,計(jì)時器繼續(xù)運(yùn)行。
平時用的每個商品都應(yīng)該有兩個屬性值,這里叫它deadLine和isOverdue吧,表示商品的到期時間和是否到期,那么倒計(jì)時可以考慮這么實(shí)現(xiàn):設(shè)置一個主計(jì)時器,每隔1秒發(fā)出消息告訴GridView現(xiàn)在的時間,GridView的Item獲得這個時間之后就和deadLine比較,如果已經(jīng)到deadline了,就把數(shù)據(jù)源中的這項(xiàng)標(biāo)記成已到期(修改isOverdue的值為true);沒到deadline,就計(jì)算還差多少時間,顯示到GridView的Item里。