Search code examples
javaandroidchronometer

Chronometer Crashes on Reset from setOnChronometerTickListener()


I'm trying to reset the the chronometer using setOnChronometerTickListener() when the chronometer reaches a certain time (in this case 5s). However it crashes when I run it on my phone. I'm using the solution to this quesion to reset the chronometer.

I've tried resetting the chronometer to different values but it still crashes at chronometer.setBase(SystemClock.elapsedRealtime());

This is how I'm implementing it:

chrono.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
      @Override
      public void onChronometerTick(Chronometer chronometer) {
              if(chronometer.getText().toString().equalsIgnoreCase("00:05")) {
                        // Reset Chronometer
                        chronometer.stop();
                        chronometer.setBase(SystemClock.elapsedRealtime());


              }
      }
});

This is the error message I get from Logcat:

2019-05-02 14:47:39.469 13143-13143/com.example.pomodoro_2 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.pomodoro_2, PID: 13143
    java.lang.StackOverflowError: stack size 8MB
        at android.widget.Chronometer.updateRunning(Chronometer.java:321)
        at android.widget.Chronometer.stop(Chronometer.java:252)
        at com.example.pomodoro_2.MainActivity$3.onChronometerTick(MainActivity.java:88)
        at android.widget.Chronometer.dispatchChronometerTick(Chronometer.java:347)
        at android.widget.Chronometer.setBase(Chronometer.java:176)

I assume from this error message that I'm overflowing the stack, but I can't figure out why and have not seen a similar error. Thanks in advance.


Solution

  • if you put a log inside your if condition, you see that log in logcat after 00:05. i prevent it by removing listener from chronometer.

    chrono.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
          @Override
          public void onChronometerTick(Chronometer chronometer) {
                  if(chronometer.getText().toString().equalsIgnoreCase("00:05")) {
                            // Reset Chronometer
                            chronometer.setOnChronometerTickListener(null);
                            chronometer.stop();
                            chronometer.setBase(SystemClock.elapsedRealtime());
    
    
                  }
          }
    });
    

    but if you need this listener, you can implements your fragment from Chronometer.OnChronometerTickListener and implement OnChronometerTickListener such as below:

      public class MainActivity extends AppCompatActivity implements Chronometer.OnChronometerTickListener {
    
        private String TAG = "MainActivity";
        Button start;
        Chronometer chronometer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            chronometer = findViewById(R.id.chron);
            start = findViewById(R.id.btn);
            start.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    chronometer.start();
                }
            });
            chronometer.start();
            chronometer.setOnChronometerTickListener(this);
    
        }
    
        @Override
        public void onChronometerTick(Chronometer chronometer) {
            if (chronometer.getText().toString().equalsIgnoreCase("00:05")) {
                // Reset Chronometer
                chronometer.setOnChronometerTickListener(null);
                chronometer.stop();
                Log.d(TAG, "onChronometerTick: stop");
    
                chronometer.setBase(SystemClock.elapsedRealtime());
                chronometer.setOnChronometerTickListener(this);
    
    
            }
    
        }
    }