Android開發用Service+Broadcast解決倒計時過程中Activity被銷燬的問題
阿新 • • 發佈:2019-02-06
說到倒計時,其實系統有一個倒計時的類叫做CountDownTimer,可是當跳轉到其他Activity時就被重置了,想到之前做藍芽4.0時的服務加廣播,就試著寫了一下,當作練習,有不對的地方請見諒。
我在onStart,onDestroy和倒計時每次更新的地方打上Log,結果如下:
可以看到,在onDestroy方法呼叫後倒計時還在繼續,下次進入Activity繼續更新UI。
主要思想是這樣的:將倒計時CountDownTimer放在Service裡面進行,每過一秒就一條發廣播,在主Activity裡註冊廣播,收到廣播後更新UI。
一、寫一個類CodeTimerService繼承自Service,重寫onStartCommand(...)方法。
先了解一下CountDownTimer怎麼用:@Override public int onStartCommand(Intent intent, int flags, int startId) { // 第一個引數是總時間, 第二個引數是間隔 mCodeTimer = new CountDownTimer(60000, 1000) { @Override public void onTick(long millisUntilFinished) { // 廣播剩餘時間 broadcastUpdate(IN_RUNNING, millisUntilFinished / 1000 + ""); } @Override public void onFinish() { // 廣播倒計時結束 broadcastUpdate(END_RUNNING); // 停止服務 stopSelf(); } }; // 開始倒計時 mCodeTimer.start(); return super.onStartCommand(intent, flags, startId); } // 傳送廣播 private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } // 傳送帶有資料的廣播 private void broadcastUpdate(final String action, String time) { final Intent intent = new Intent(action); intent.putExtra("time", time); sendBroadcast(intent); }
建立CountDownTimer例項時傳入兩個引數,第一個引數是總時間, 第二個引數是間隔;需要重寫onTick(long millisUntilFinished)和onFinish()兩個回撥方法,前者表示倒計時進行中,後者表示倒計時結束,在方法中寫處理事件;最後呼叫start()方法開始倒計時。
二、在主Activity中註冊廣播,接收廣播,更新UI
// 註冊廣播 private static IntentFilter updateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(RegisterCodeTimerService.IN_RUNNING); intentFilter.addAction(RegisterCodeTimerService.END_RUNNING); return intentFilter; } // 廣播接收者 private final BroadcastReceiver mUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); switch (action) { case RegisterCodeTimerService.IN_RUNNING: if (btnCountdown.isEnabled()) btnCountdown.setEnabled(false); // 正在倒計時 btnCountdown.setText("倒計時中(" + intent.getStringExtra("time") + ")"); Log.e(TAG, "倒計時中(" + intent.getStringExtra("time") + ")"); break; case RegisterCodeTimerService.END_RUNNING: // 完成倒計時 btnCountdown.setEnabled(true); btnCountdown.setText(R.string.countdown); break; } } }; @Override protected void onResume() { super.onResume(); // 註冊廣播 registerReceiver(mUpdateReceiver, updateIntentFilter()); } @Override protected void onPause() { super.onPause(); // 移除註冊 unregisterReceiver(mUpdateReceiver); }
三、開始倒計時
當按鈕被點選時,呼叫startService(mIntent)方法,啟動倒計時的服務。