Таймер обратного отсчета, как реализовать метод onfinish

У меня есть таймер обратного отсчета, который я хочу реализовать в методе завершения или какой-то код, чтобы, когда таймер останавливается, текстовые представления менялись на Время истекло и инициировался другой метод (в активность). Чтобы уточнить, таймеру присваивается начальное число, которое ведет отсчет до нуля в формате xx:xx.

Класс таймера:

public class countdown_timer {
private  long pls;
private long millisInFuture;
private long countDownInterval;
private boolean status;
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
    this.millisInFuture = pMillisInFuture;
    this.countDownInterval = pCountDownInterval;
    this.pls = pMillisInFuture;

    status = false;
    Initialize();
}

public void Stop() {
    status = false;
}
public  void Reset() {
    millisInFuture = pls;
}

public long getCurrentTime() {
    return millisInFuture;
}

public void Start() {
    status = true;
}
public void Initialize()
{
    final Handler handler = new Handler();
    Log.v("status", "starting");
    final Runnable counter = new Runnable(){

        public void run(){
            long sec = millisInFuture/1000;
            if(status) {
                if(millisInFuture <= 0) {
                    Log.v("status", "done");
                } else {
                    Log.v("status", Long.toString(sec) + " seconds remain");
                    millisInFuture -= countDownInterval;
                    handler.postDelayed(this, countDownInterval);
                }
            } else {
                Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
                handler.postDelayed(this, countDownInterval);
            }
        }
    };

    handler.postDelayed(counter, countDownInterval);
}

Активность, которую использует таймер:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_card_game_2);
    //...find views
    mycounterup = new countdown_timer(startcard, 1000);
    mycounterdown = new countdown_timer(startcard, 1000);
    RefreshTimer();
    mycounterdown.Start();

  public void RefreshTimer()
{
    final Handler handler = new Handler();
    final Runnable counter = new Runnable(){

        public void run(){
            int minutes_up_start = (int) (mycounterup.getCurrentTime() / 1000) / 60;
            int seconds_up_start = (int) (mycounterup.getCurrentTime() / 1000) % 60;
            String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
            card_2_up.setText(time_2_up_start_formatted);

            int minutes_down_start = (int) (mycounterdown.getCurrentTime() / 1000) / 60;
            int seconds_down_start = (int) (mycounterdown.getCurrentTime() / 1000) % 60;
            String card_2_down_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_down_start, seconds_down_start);
            card_2_down.setText(card_2_down_start_formatted);
            handler.postDelayed(this, 100);
        }
    };

    handler.postDelayed(counter, 100);
}

person Community    schedule 12.03.2018    source источник
comment
Вы можете попытаться расширить CountDownTimer в своем классе таймера.   -  person Cagri Yalcin    schedule 12.03.2018
comment
@Cagri Yalcin, не могли бы вы рассказать мне, как мне это сделать, пожалуйста?   -  person    schedule 12.03.2018
comment
почему вы не используете встроенный класс CountDownTimer?   -  person godot    schedule 12.03.2018
comment
@godot, что ты имеешь в виду?   -  person    schedule 12.03.2018
comment
@manos проверь мой ответ. Надеюсь, поможет.   -  person Cagri Yalcin    schedule 12.03.2018


Ответы (2)


Вы можете использовать CountDownTimer:

new CountDownTimer(endsIn * 1000, 1000) { 
public void onTick(long millisUntilFinished) { 
           timerTextView.setText(String.valueOf(millisUntilFinished/1000);
 } 
public void onFinish() {
} 
}.start();

ИЛИ:

расширить класс CountDownTimer:

public class countdown_timer extends CountDownTimer {
    TextView textView;
    @Override
    public void onTick(long millisInFuture) {
        long sec = millisInFuture/1000;
            if(millisInFuture <= 0) {
                Log.v("status", "done");

        } else {
            Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
        }
    }

    @Override
    public void onFinish() {
        if(textView != null){
            // change text in your textview
        }
    }



    public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
        super(pMillisInFuture, pCountDownInterval);

    }
    public countdown_timer(TextView textView, long pMillisInFuture, long pCountDownInterval) {
        super(pMillisInFuture, pCountDownInterval);
        this.textView = textView;




    }






}

вот два конструктора, один из них такой же, как в вашем примере, а во втором вы также можете передать объект TextView и использовать его в методе onFinish().

ОБНОВЛЕНИЕ 2:

Вот CountDownTimer в действии:

public class MainActivity extends AppCompatActivity {

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

        long startcard = 10000;
        textView = (TextView) findViewById(R.id.test);

        mycounterdown = new CountDownTimer(startcard, 1000) {
            @Override
            public void onTick(long mycounterup) {
                int minutes_up_start = (int) (mycounterup / 1000) / 60;
                int seconds_up_start = (int) (mycounterup / 1000) % 60;
                String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
                textView.setText(time_2_up_start_formatted);
            }

            @Override
            public void onFinish() {
                // call here other methods from activity

                testMethod();
            }
        };
        mycounterdown.start();

    }
    public void testMethod(){
        Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
    }

}

ОБНОВЛЕНИЕ 3: если последний тик равен единице, а не нулю, измените интервал обратного отсчета на 500 вместо 1000:

public class MainActivity extends AppCompatActivity {

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

        long startcard = 10000;
        textView = (TextView) findViewById(R.id.test);

        mycounterdown = new CountDownTimer(startcard, 500) {
            @Override
            public void onTick(long mycounterup) {
                int minutes_up_start = (int) (mycounterup / 1000) / 60;
                int seconds_up_start = (int) (mycounterup / 1000) % 60;
                String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
                textView.setText(time_2_up_start_formatted);
            }

            @Override
            public void onFinish() {
                // call here other methods from activity

                testMethod();
            }
        };
        mycounterdown.start();

    }
    public void testMethod(){
        Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
    }

}

ПРИМЕЧАНИЕ. взгляните на этот ответ

person godot    schedule 12.03.2018
comment
Проблема в том, что с обычным таймером обратного отсчета много ошибок, таких как пропуск последнего тика, поэтому я создал для него класс - person ; 12.03.2018
comment
что вы имеете в виду, пропуская последний тик? - person godot; 12.03.2018
comment
если вы имеете в виду последний тик, когда время будет равно нулю, вы можете просто написать if(millisUntilFinished/1000!=0){ //делать что-то} - person godot; 12.03.2018
comment
Спасибо за помощь, но я не хочу добавлять новый CountDownTimer, я хочу использовать тот, который у меня есть в классе таймера, но с методом завершения - person ; 12.03.2018
comment
Как я могу инициировать другой метод, когда таймер останавливается? - person ; 12.03.2018
comment
метод из Activity? - person godot; 12.03.2018
comment
Да метод из деятельности - person ; 12.03.2018
comment
если вы хотите вызывать методы активности, почему вы хотите использовать собственный таймер обратного отсчета, а не тот, который я описал в первый раз? - person godot; 12.03.2018
comment
потому что пользовательский более точен - person ; 12.03.2018
comment
с какой неточностью вы столкнулись? - person godot; 12.03.2018
comment
обычный останавливается на 00:02, затем отсчитывает 2 секунды в фоновом режиме, а затем отображается текст времени вместо отображения 00:01, затем 00:00, а затем время истекло - person ; 12.03.2018
comment
проверьте это еще раз, я обновил свой ответ. Я попытался переписать вашу логику без специального таймера обратного отсчета. - person godot; 12.03.2018
comment
Останавливается на 1 секунду вместо 0 - person ; 12.03.2018

Во-первых, расширьте CountDownTimer в своем классе таймера.

public class countdown_timer extends CountDownTimer {

}

Это позволяет реализовать некоторые методы.

@Override
public void onTick(long l) {

}

@Override
public void onFinish() {

}

Также вы должны реализовать конструктор, соответствующий суперклассу. Вы также можете добавить некоторые дополнительные параметры. Например TextView

TextView textView;
public countdown_timer(long millisInFuture, long countDownInterval, TextView txt) {
    super(millisInFuture, countDownInterval);
    textView = txt;
}

onFinish() это то, что вам нужно. Также убедитесь, что вы используете этот класс как CountDownTimer. После этого вы сможете запустить свой таймер. Надеюсь, поможет.

person Cagri Yalcin    schedule 12.03.2018
comment
Когда я расширяю класс до CountDownTimer, он показывает мне ошибку: public countdown_timer (long pMillisInFuture, long pCountDownInterval) Нет доступного конструктора по умолчанию - person ; 12.03.2018
comment
Вы должны реализовать конструктор, соответствующий вашему суперклассу. Редактирование моего ответа - person Cagri Yalcin; 12.03.2018
comment
Пока все хорошо, но метод завершения находится в классе таймера, а не в моей деятельности, поэтому я не могу использовать его для изменения текста. - person ; 12.03.2018
comment
Вы можете изменить метод конструктора, чтобы отправить файл Textview. Проверьте мой отредактированный ответ - person Cagri Yalcin; 12.03.2018
comment
Как я могу инициировать другой метод, когда таймер останавливается? - person ; 12.03.2018
comment
Какой метод?. - person Cagri Yalcin; 12.03.2018
comment
пользовательский метод в моей деятельности - person ; 12.03.2018
comment
Вы должны использовать метод onTick() для обновления вашего TextViews - person Cagri Yalcin; 12.03.2018