Держите CountDownTimer работающим после изменения ориентации

Я сделал CountDownTimer, который отлично работает - вы можете получить правильное время для мягкого / среднего / крутого яйца. Моя проблема в том, что таймер сбрасывается после изменения ориентации. Я гуглил и пробовал так много решений, но до сих пор не понимаю, как правильно использовать onSave и onRestore. Вот мой код:

Какие-нибудь советы?

    package com.dohman.boilaneggbae;

import android.graphics.PorterDuff;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    private static final String CURRENT_TIME = "currentTime";
    private static final String DURATION_TIME = "durationTime";
    private long currentTime;
    private int durationTime;
    private TextView time;
    private Button buttonLargeSize;
    private Button buttonMediumSize;
    private Button buttonSoft;
    private Button buttonMedium;
    private Button buttonHard;
    private Button buttonHellaHard;
    private CountDownTimer countDownTimer;
    private EggSize mediumOrLarge = EggSize.UNDEFINED;
    private boolean alreadyRunning = false;

    enum EggSize {
        UNDEFINED, MEDIUM, LARGE;
    }

    private View.OnClickListener btnMediumSizeClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mediumOrLarge = EggSize.MEDIUM;
        }
    };

    private View.OnClickListener btnLargeSizeClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mediumOrLarge = EggSize.LARGE;
        }
    };

    private View.OnClickListener btnSoftClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if ((mediumOrLarge != EggSize.UNDEFINED) && (alreadyRunning == false)) {
                alreadyRunning = true;
                durationTime = 240;
                start(240);
            } else if (mediumOrLarge == EggSize.UNDEFINED) {
                time.setText("Choose size first");
            } else {
                alreadyRunning = false;
                cancel();
            }
        }
    };

    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putLong(CURRENT_TIME, currentTime);
        savedInstanceState.putInt(DURATION_TIME, durationTime);
        super.onSaveInstanceState(savedInstanceState);
    }

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

        if (savedInstanceState != null) {
            currentTime = savedInstanceState.getLong(CURRENT_TIME);
            durationTime = savedInstanceState.getInt(DURATION_TIME);
        }

        time = findViewById(R.id.time);
    }

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

        currentTime = savedInstanceState.getLong(CURRENT_TIME);
        durationTime = savedInstanceState.getInt(DURATION_TIME);

        currentTime -= durationTime;
    }

    private void start(int duration) {
        time.setText("");

        if (mediumOrLarge == EggSize.MEDIUM) {
            duration -= 60;
        }
        countDownTimer = new CountDownTimer(duration * 1000, 1000) {

            @Override
            public void onTick(long millisUntilFinished) {
                String text = String.format(Locale.getDefault(), "%02d:%02d",
                        TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) % 60,
                        TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) % 60);
                time.setText(text);
            }

        countDownTimer.start();
    }
}

person Dohman    schedule 27.01.2018    source источник
comment
Подробнее об этом можно узнать в ДОКУМЕНТАЦИИ и для достижения желаемого. Вы можете сохранить время запуска таймера и его продолжительность. Затем, когда вы восстанавливаете состояние, вы можете воссоздать таймер на setDuration - (currentTime - timerStartedTime) длительность.   -  person Titus    schedule 27.01.2018
comment
В какой переменной я должен хранить таймер? Нить?   -  person Dohman    schedule 27.01.2018
comment
Вы можете сохранить текущее время как long и продолжительность как int.   -  person Titus    schedule 27.01.2018
comment
Теперь я закодировал все, что мог, отредактировал свою заявку и даже удалил несвязанные коды, чтобы вам было легче читать. Я создал onSave и onRestore и попытался найти один из способов сохранения и восстановления, но все равно не работает.   -  person Dohman    schedule 27.01.2018


Ответы (1)


Я наконец решил это! По этой ссылке: https://codinginflow.com/code-examples/android/countdown-timer/part-2

Это коды:

package com.codinginflow.countdowntimerexample;

import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.Locale;

public class MainActivity extends AppCompatActivity {
    private static final long START_TIME_IN_MILLIS = 600000;

    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;
                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("endTime");
            mTimeLeftInMillis = mEndTime - System.currentTimeMillis();
            startTimer();
        }
    }
}

EDIT: по какой-то причине я не могу отметить свой ответ как решение, но эта проблема все равно решена. (Отвечено)

person Dohman    schedule 27.01.2018
comment
Вам нужно подождать 48 часов, чтобы принять свой собственный ответ: stackoverflow.com/help/self-answer Как было предложено, добавьте необходимые части вашего ответа. Ссылки могут стать недействительными в будущем. - person Udo Held; 28.01.2018