倒数计时器似乎在后台更改后仍在后台运行(人像变为横向,反之亦然)

问题描述 投票:0回答:1

我做了一个倒数计时器,我希望它即使在改变方向后也能继续运行。但是说当我启动计时器,然后改变方向然后暂停时,计时器似乎在后台运行。我通过在onFinish()函数中显示提示消息来检查它是否在后台运行,并且它似乎在后台运行。反正有解决办法吗?

import android.os.CountDownTimer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Locale;


public class MainActivity extends AppCompatActivity {

    private static final long START_TIME_IN_MILLIS = 10000;

    private TextView mTextViewCountDown;
    private Button mButtonStartPause;
    private Button mButtonReset;

    private CountDownTimer mCountDownTimer;

    private boolean mTimerRunning;

    private long mTimeLeftInMillis = START_TIME_IN_MILLIS;
    private long mEndTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextViewCountDown = findViewById(R.id.text_view_countdown);

        mButtonStartPause = findViewById(R.id.button_start_pause);
        mButtonReset = findViewById(R.id.button_reset);

        mButtonStartPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mTimerRunning) {
                    pauseTimer();
                } else {
                    startTimer();
                }
            }
        });

        mButtonReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetTimer();
            }
        });

        updateCountDownText();
    }

    private void startTimer() {
        mEndTime = System.currentTimeMillis() + mTimeLeftInMillis;

        mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mTimeLeftInMillis = millisUntilFinished;
                updateCountDownText();
            }

            @Override
            public void onFinish() {
                mTimerRunning = false;
                Toast.makeText(MainActivity.this, "TIMER RUNNING IN BACKGROUND..!!! ", Toast.LENGTH_SHORT).show();
                updateButtons();
            }
        }.start();

        mTimerRunning = true;
        updateButtons();
    }

    private void pauseTimer() {
        mCountDownTimer.cancel();
        mTimerRunning = false;
        updateButtons();
    }

    private void resetTimer() {
        mTimeLeftInMillis = START_TIME_IN_MILLIS;
        updateCountDownText();
        updateButtons();
    }

    private void updateCountDownText() {
        int minutes = (int) (mTimeLeftInMillis / 1000) / 60;
        int seconds = (int) (mTimeLeftInMillis / 1000) % 60;

        String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);

        mTextViewCountDown.setText(timeLeftFormatted);
    }

    private void updateButtons() {
        if (mTimerRunning) {
            mButtonReset.setVisibility(View.INVISIBLE);
            mButtonStartPause.setText("Pause");
        } else {
            mButtonStartPause.setText("Start");

            if (mTimeLeftInMillis < 1000) {
                mButtonStartPause.setVisibility(View.INVISIBLE);
            } else {
                mButtonStartPause.setVisibility(View.VISIBLE);
            }

            if (mTimeLeftInMillis < START_TIME_IN_MILLIS) {
                mButtonReset.setVisibility(View.VISIBLE);
            } else {
                mButtonReset.setVisibility(View.INVISIBLE);
            }
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong("millisLeft", mTimeLeftInMillis);
        outState.putBoolean("timerRunning", mTimerRunning);
        outState.putLong("endTime", mEndTime);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        mTimeLeftInMillis = savedInstanceState.getLong("millisLeft");
        mTimerRunning = savedInstanceState.getBoolean("timerRunning");
        updateCountDownText();
        updateButtons();

        if (mTimerRunning) {
            mEndTime = savedInstanceState.getLong(enter code here"endTime");
            mTimeLeftInMillis = mEndTime - System.currentTimeMillis();
            startTimer();
        }
    }
}
java android countdowntimer
1个回答
0
投票

您可以将倒数逻辑和数据移至ViewModel

ViewModel类旨在以生命周期感知的方式存储和管理与UI相关的数据。 ViewModel类允许数据在配置更改(例如屏幕旋转)中保留下来。

MainViewModel代码可能是:

package com.example.countdown;

import androidx.lifecycle.ViewModel;

public class MainViewModel extends ViewModel {
    private static final long START_TIME_IN_MILLIS = 10000;
    private boolean mTimerRunning;
    private long mTimeLeftInMillis = START_TIME_IN_MILLIS;
    private long mEndTime;

    boolean getTimerRunning() {
        return mTimerRunning;
    }

    void setTimerRunning(boolean timerRunning) {
        this.mTimerRunning = timerRunning;
    }

    long getTimeLeftInMillis() {
        return mTimeLeftInMillis;
    }

    void setTimeLeftInMillis(long timeLeftInMillis) {
        this.mTimeLeftInMillis = timeLeftInMillis;
    }

    long getEndTime() {
        return mEndTime;
    }

    void setEndTime(long endTime) {
        this.mEndTime = endTime;
    }

    void startTimer() {
        mEndTime = System.currentTimeMillis() + mTimeLeftInMillis;
        mTimerRunning = true;
    }

    void finish() {
        mTimerRunning = false;
    }

    void restart() {
        mTimeLeftInMillis = START_TIME_IN_MILLIS;
    }

    void updateCounter(long millisUntilFinished) {
        mTimeLeftInMillis = millisUntilFinished;
    }

    boolean remainingTime() {
        return mTimeLeftInMillis < START_TIME_IN_MILLIS;
    }
}

和MainActivity:

package com.example.countdown;

import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    protected MainViewModel viewModel;
    private TextView mTextViewCountDown;
    private Button mButtonStartPause;
    private Button mButtonReset;

    private CountDownTimer mCountDownTimer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewModel = new ViewModelProvider(this).get(MainViewModel.class);

        mTextViewCountDown = findViewById(R.id.text_view_countdown);

        mButtonStartPause = findViewById(R.id.button_start_pause);
        mButtonReset = findViewById(R.id.button_reset);

        mButtonStartPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (viewModel.getTimerRunning()) {
                    pauseTimer();
                } else {
                    startTimer();
                }
            }
        });

        mButtonReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetTimer();
            }
        });

        updateCountDownText();
    }

    private void startTimer() {
        viewModel.startTimer();

        mCountDownTimer = new CountDownTimer(viewModel.getTimeLeftInMillis(), 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                viewModel.updateCounter(millisUntilFinished);
                updateCountDownText();
            }

            @Override
            public void onFinish() {
                viewModel.finish();
                Toast.makeText(MainActivity.this, "TIMER RUNNING IN BACKGROUND..!!! ", Toast.LENGTH_SHORT).show();
                updateButtons();
            }
        }.start();

        updateButtons();
    }

    private void pauseTimer() {
        mCountDownTimer.cancel();
        viewModel.finish();
        updateButtons();
    }

    private void resetTimer() {
        viewModel.restart();
        updateCountDownText();
        updateButtons();
    }

    private void updateCountDownText() {
        int minutes = (int) (viewModel.getTimeLeftInMillis() / 1000) / 60;
        int seconds = (int) (viewModel.getTimeLeftInMillis() / 1000) % 60;

        String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);

        mTextViewCountDown.setText(timeLeftFormatted);
    }

    private void updateButtons() {
        if (viewModel.getTimerRunning()) {
            mButtonReset.setVisibility(View.INVISIBLE);
            mButtonStartPause.setText("Pause");
        } else {
            mButtonStartPause.setText("Start");

            if (viewModel.getTimeLeftInMillis() < 1000) {
                mButtonStartPause.setVisibility(View.INVISIBLE);
            } else {
                mButtonStartPause.setVisibility(View.VISIBLE);
            }

            if (viewModel.remainingTime()) {
                mButtonReset.setVisibility(View.VISIBLE);
            } else {
                mButtonReset.setVisibility(View.INVISIBLE);
            }
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong("millisLeft", viewModel.getTimeLeftInMillis());
        outState.putBoolean("timerRunning", viewModel.getTimerRunning());
        outState.putLong("endTime", viewModel.getEndTime());
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        viewModel.setTimeLeftInMillis(savedInstanceState.getLong("millisLeft"));
        viewModel.setTimerRunning(savedInstanceState.getBoolean("timerRunning"));
        updateCountDownText();
        updateButtons();

        if (viewModel.getTimerRunning()) {
            viewModel.setEndTime(savedInstanceState.getLong("endTime"));
            viewModel.setTimeLeftInMillis(viewModel.getEndTime() - System.currentTimeMillis());
            startTimer();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.