1. 程式人生 > >Android開發用Service+Broadcast解決倒計時過程中Activity被銷燬的問題

Android開發用Service+Broadcast解決倒計時過程中Activity被銷燬的問題

說到倒計時,其實系統有一個倒計時的類叫做CountDownTimer,可是當跳轉到其他Activity時就被重置了,想到之前做藍芽4.0時的服務加廣播,就試著寫了一下,當作練習,有不對的地方請見諒。

我在onStart,onDestroy和倒計時每次更新的地方打上Log,結果如下:


可以看到,在onDestroy方法呼叫後倒計時還在繼續,下次進入Activity繼續更新UI。

主要思想是這樣的:將倒計時CountDownTimer放在Service裡面進行,每過一秒就一條發廣播,在主Activity裡註冊廣播,收到廣播後更新UI。
一、寫一個類CodeTimerService繼承自Service,重寫onStartCommand(...)方法。

@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怎麼用:
建立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)方法,啟動倒計時的服務。