① android將倒計時做到極致
在開發倒計時功能時往往我們會為了方便直接使用CountDownTimer或者使用Handler做延時來實現,當然CountDownTimer內部封裝也是使用的Handler。
如果只是做次數很少的倒計時或者不需要精確的倒計時邏輯那倒沒關系,比如說我只要倒計時10秒,或者我大概5分鍾請求某個介面
但是如果是需要做精確的倒計時操作,比如說手機發送驗證碼60秒,那使用現有的倒計時方案就會存在問題。可能有些朋友沒有注意到這一點,下面我們就來簡單分析一下現有倒計時的問題。
這個可能是用得最多的,因為方便嘛。但其實倒計時每一輪倒計時完之後都是存在誤差的,如果看過CountDownTimer的源碼你就會知道,他的內部是有做 校準操作 的。(源碼很簡單這里就不分析了)
但是如果你認真的測試過CountDownTimer,你就會發現,即便它內部有做校準操作,他的沒一輪都是有偏差,只是他最後一次倒計時完之後的總共時間和開始倒計時的時間相比沒偏差。
什麼意思呢,意思就是1秒,2.050秒,3.1秒......,這樣的每輪偏差,導致他會出現10.95秒,下一次12秒的情況,那它的回調中如果你直接做取整就會出現少一秒的情況,但實際是沒少的。
這只是其中的一個問題,你可以不根據它的回調做展示,自己用一個整形累加做展示也能解決。但是他還有個問題,有概率直接出現跳秒,就是比如3秒,下次直接5秒,這是實際的跳秒,是少了一次回調的那種。
跳秒導致你如果直接使用它可能會大問題,你可能自測的時候沒發現,到時一上線應用在用戶那概率跳秒,那就蛋疼了。
不搞這么多花里胡哨的,直接使用Handler來實現,會有什麼問題。
因為直接使用handler來實現,沒有校準操作,每次循環會出現幾毫秒的誤差,雖然比CountDownTimer的十幾毫秒的誤差要好, 但是在基數大的倒計時情況下誤差會累計,導致最終結果和現實時間差幾秒誤差,時間越久,誤差越大
直接使用Timer也一樣,只不過他每輪的誤差更小,幾輪才有1毫秒的誤差,但是沒有校準還是會出現誤差累計,時間越久誤差越大。
既然無法直接使用原生的,那我們就自己做一個。
我們基於Handler進行封裝,從上面可以看出主要為了解決兩個問題,時間校準和跳秒。自己寫一個CountDownTimer
思路就是在倒計時開始前獲取一次SystemClock.elapsedRealtime(),沒輪倒計時再獲取一次SystemClock.elapsedRealtime()相減得到誤差,根據delay校準。然後使用while循壞來處理跳秒的操作,與原生的CountDownTimer不同,這里如果跳了多少秒,就會返回多少次回調。
② 接受驗證碼用什麼控制項 android
android接收驗證碼用的控制項可以是button,textview 都帶有點擊效果,如果是輸入驗證碼可以用edittext ,這個沒有什麼爭議,也可以自己定製控制項,根據實際的需求來
③ android 用 service 和 CountDownTimer 實現一個倒計時器的功能
在平時我們編程的時候,經常會用到倒計時這個功能,很多人不知道Android已經幫封裝好了一個類,往往都自己寫。現在發現了這個類,大家共享一下:
在一個TextView不斷顯示剩下的時間,代碼如下:
[java] view plain
private TextView vertifyView;
private CountDownTimer timer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
vertifyView.setText((millisUntilFinished / 1000) + "秒後可重發");
}
@Override
public void onFinish() {
vertifyView.setEnabled(true);
vertifyView.setText("獲取驗證碼");
}
};
調用的時候很簡單:timer.start();
最後說明一下:CountDownTimer timer = new CountDownTimer(10000, 1000)中,第一個參數表示總時間,第二個參數表示間隔時間。意思就是每隔一秒會回調一次方法onTick,然後10秒之後會回調onFinish方法。
④ Android實現計時與倒計時的幾種方法
Android實現計時與倒計橡冊時的五種含模方法:
方梁老宏法一
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);
}
};
}
linux
方法二
Handler與Thread(不佔用UI線程)
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) {
}
}
}
}
}
方法三
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.schele(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);
}
}
});
}
};
}
方法四
TimerTask與Handler(不用Timer的改進型)
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.schele(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與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);
}
};
}
計時與倒計時
方法1,方法2和方法3,都是倒計時
方法4,方法5,都是計時
計時和倒計時,都可使用上述方法實現(代碼稍加改動)
UI線程比較
方法1,方法2和方法3,都是在UI線程實現的計時;
方法4和方法5,是另開Runnable線程實現計時
實現方式比較
方法1,採用的是Java實現,即Timer和TimerTask方式;
其它四種方法,都採用了Handler消息處理
推薦使用
如果對UI線程交互要求不很高,可以選擇方法2和方法3
如果考慮到UI線程阻塞,嚴重影響到用戶體驗,推薦使用方法4,另起線程單獨用於計時和其它的邏輯處理
方法5,綜合了前幾種方法的優點,是最簡的