當前位置:首頁 » 安卓系統 » 安卓中的計時器屬於什麼線程

安卓中的計時器屬於什麼線程

發布時間: 2023-05-23 14:42:14

Ⅰ android中怎麼使timecount自動開始計時

android計時器,時間計算器的實現方法,需要的朋友可以參考一下

需求:默認為"00:00:00",點擊開始按鈕時清零後開始計時,出現如10:28:34。點擊停止的時候停止計時。
問題:使用Calendar
DateFormat的方法,不設置時區獲取到的小時是本地時區的(東八區的就是8),設置成GMT標准時區獲取到的時間是12小時(12:00:00),設置24小時制無效。
在開始時間加減各種小時都無效,而且計時只能到12小時就自動跳上去了,始終無法出現默認狀態00:00:00開始計時的效果。
嘗試各種時間設置方法無效後只能自己寫一個根據秒數轉換時間格式字元串的方法了,經過測試是沒問題的,兩位數只能顯示99小時為最大,如需要更大小時數需要改改方法。
另外小時數也不能無限大,超過long數據類型長度會變成負數的,會出現異常的。

顯示效果:

測試類:

復制代碼
代碼如下:

public class TestTime {
public
static void main(String[] args) {
TestTime tt = new
TestTime();
tt.showTimeCount(99*3600000+75*1000);

}

//時間計數器,最多隻能到99小時,如需要更大小時數需要改改方法
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;
}

}

實際例子:

復制代碼
代碼如下:

//時間計數器,最多隻能到99小時,如需要更大小時數需要改改方法

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");
// 清零 開始計時

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);
}
};

//啟動計時線程,定時更新
mTicker.run();

}else{
b.setText("Start");
//停止計時 Remove
any pending posts of Runnable r that are in the message
queue.

stepTimeHandler.removeCallbacks(mTicker);
}

}
}

用時間格式化的方式測試代碼:

復制代碼
代碼如下:

//開始按鈕 通過Calendar時間設置的方式,無法正常顯示小時為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");
// 清零 開始計時

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()
//記錄從機器啟動後到現在的毫秒數,當系統進入深度睡眠時,此計時器將會停止

//System.currentTimeMillis()
//返回自1970年1月1日到現在的毫秒數,通常用來設置日期和時間
//System.elapsedRealtime()
//返回從機器啟動後到現在的毫秒數,包括系統深度睡眠的時間,api里沒有這個方法

//直接取得的是當地時區時間,當地時間跟時區有關,設置GMT後始終多12小時
startTime =
System.currentTimeMillis();//12*3600000 - 36*3600000減掉或者加上12小時都不行

mTicker = new Runnable() {
public
void run() {
//這個減出來的日期是1970年的 時間格式不能出現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);
}
};

//啟動計時線程,定時更新
mTicker.run();

}else{
b.setText("Start");
//停止計時 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;

Ⅱ android 計時器代碼

Timer mTimer = new Timer();
mTask = new TimerTask(){
public void run(){
//execute the task
Message message = new Message();
message.what = DIALOG_HIDE;
//Log.e(TAG, "message.what = DIALOG_HIDE");
mHandler.sendMessage(message);
}
};
mTimer.schele(mTask, 5000);
在主線程里開啟timer,等於啟動了另一個線程,線程之間的通信是要用handler發送message,然後在主線程里用handler.handleMessage()裡面接收並處理。

Ⅲ android service+broadcastreceiver怎麼實現秒錶計時器

Service起線程監聽系統時間,系統時間變化一定毫秒數之後發Broadcast,在Activity裡面做broadcastreceiver來接收Service發的廣播來更新顯示。

如果你需要應用在後台的時候也在計時的話才需要Service,否則直接在Activity里用Handler單起一個線程也可以。

Ⅳ android中looper的實現原理,為什麼調用looper.prepare就在當前線程關聯了一個lo

實際上:消息發送和計劃任務提交之後,它們都會進入某線程的消息隊列中,我們可以把這個線程稱之為目標線程。不論是主線程還是子線程都可以成為目標線程。上例中之所以在主線程中處理消息,是因為我們要更新UI,按照android中的規定我們必須由主線程更新UI。所以我們讓主線程成為了目標線程。

那麼如何控制讓某個線程成為目標線程呢?

這就引出了Looper的概念。Android系統中實現了消息循環機制,Android的消息循環是針對線程的,每個線程都可以有自己的消息隊列和消息循環。Android系統中的通過Looper幫助線程維護著一個消息隊列和消息循環。通過Looper.myLooper()得到當前線程的Looper對象,通過Looper.getMainLooper()得到當前進程的主線程的Looper對象。
前面提到每個線程都可以有自己的消息隊列和消息循環,然而我們自己創建的線程默認是沒有消息隊列和消息循環的(及Looper),要想讓一個線程具有消息處理機制我們應該在線程中先調用Looper.prepare()來創建一個Looper對象,然後調用Looper.loop()進入消息循環。如上面的源碼所示。
當我們用Handler的構造方法創建Handler對象時,指定handler對象與哪個具有消息處理機制的線程(具有Looper的線程)相關聯,這個線程就成了目標線程,可以接受消息和計劃任務了。Handler中的構造方法如下:

[java] view
plainprint?

public Handler() {

if (FIND_POTENTIAL_LEAKS) {

final Class<? extends Handler> klass = getClass();

if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

(klass.getModifiers() & Modifier.STATIC) == 0) {

Log.w(TAG, "The following Handler class should be static or leaks might occur: " +

klass.getCanonicalName());

}

}

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

"Can't create handler inside thread that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = null;

}

public Handler(Looper looper) {

mLooper = looper;

mQueue = looper.mQueue;

mCallback = null;

}
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}

mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}

public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}

在上述的計時器的例子中,之所以可以在主線程中處理消息而我們自己並沒有調用Looper.prepare()等方法,是因為Android系統在Activity啟動時為其創建一個消息隊列和消息循環,當我們用無參的Handler構造方法創建對象時又用了當前線程的Looper對象,及將handler與主線程中的Looper對象進行了關聯。

android中是使用Looper機制來完成消息循環的,但每次創建線程時都先初始化Looper比較麻煩,因此Android為我們提供了一個HandlerThread類,他封裝了Looper對象,是我們不用關心Looper的開啟和釋放問題。

不管是主線程還是其他線程只要有Looper的線程,別的線程就可以向這個線程的消息隊列中發送消息和任務。

我們使用HandlerThread類代替上一篇文章中的子線程,並用HandlerThread類中的Looper對象構造Handler,則接受消息的目標線程就不是主線程了,而是HandlerThread線程。代碼如下:

[java] view
plainprint?

public class clockActivity extends Activity {

/** Called when the activity is first created. */

private String TAG="clockActivity";

private Button endButton;

private TextView textView;

private int timer=0;

private boolean isRunning=true;

private Handler handler;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

endButton=(Button)findViewById(R.id.endBtn);

textView=(TextView)findViewById(R.id.textview);

endButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

isRunning=false;

}

});

HandlerThread thread=new HandlerThread("myThread");

handler=new Handler(thread.getLooper());//與HandlerThread中的Looper對象關聯

thread.start();

Runnable r=new Runnable(){

@Override

public void run() {

// TODO Auto-generated method stub

if(isRunning){

textView.setText("走了"+timer+"秒");

timer++;

handler.postDelayed(this, 1000);//提交任務r,延時1秒執行

}

}

};

handler.postDelayed(r, 1000);

}

}
public class clockActivity extends Activity {
/** Called when the activity is first created. */
private String TAG="clockActivity";
private Button endButton;
private TextView textView;
private int timer=0;
private boolean isRunning=true;
private Handler handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
endButton=(Button)findViewById(R.id.endBtn);
textView=(TextView)findViewById(R.id.textview);
endButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
isRunning=false;
}
});
HandlerThread thread=new HandlerThread("myThread");
handler=new Handler(thread.getLooper());//與HandlerThread中的Looper對象關聯
thread.start();
Runnable r=new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
if(isRunning){
textView.setText("走了"+timer+"秒");
timer++;
handler.postDelayed(this, 1000);//提交任務r,延時1秒執行
}
}
};
handler.postDelayed(r, 1000);
}
}

此時處理任務會在handlerThread線程中完成。當然這個例子會出線異常:依然是因為在非主線程中更新了UI。這樣做只是為了大家能夠理解這種機制。

深入理解Android消息處理機制對於應用程序開發非常重要,也可以讓我們對線程同步有更加深刻的認識,希望這篇文章可以對朋友們有所幫助。

熱點內容
銳志哪個配置性價比最高 發布:2025-02-12 17:38:43 瀏覽:918
智能推送演算法 發布:2025-02-12 17:38:41 瀏覽:835
拍照上傳器 發布:2025-02-12 17:34:29 瀏覽:652
androidweb框架 發布:2025-02-12 17:32:45 瀏覽:76
安卓編程賀卡 發布:2025-02-12 17:32:44 瀏覽:838
php獲取資料庫的欄位 發布:2025-02-12 17:29:02 瀏覽:766
伺服器地址消失 發布:2025-02-12 17:23:36 瀏覽:951
後台執行php腳本 發布:2025-02-12 17:21:45 瀏覽:471
spring編程式事務 發布:2025-02-12 17:16:55 瀏覽:398
nginx禁止ip訪問 發布:2025-02-12 17:15:14 瀏覽:274