简体   繁体   中英

Handler randomly stops updating setText

I made a runnable stopwatch, it works and updates the time correctly most of the time. But sometimes when I switch to another fragment and then switch back it will run for a random amount of seconds (anywhere from 2-15) and then stop. The handler is still running but the text is not being updated. When I switch fragments again and back and it skips to the correct time and then resumes ticking. It's very strange because it doesn't do this every time I switch fragments, but it's happening fairly often.

//code in fragment 1 class
 start.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            if (!MainActivity.timeOn && spinner.getSelectedItem()!=null){

                MainActivity.timeOn=true;
                if(MainActivity.timeOn) {
                    MainActivity.paused = false;
                    MainActivity.stopTime=false;
                    MainActivity.StartTime = SystemClock.uptimeMillis();
                    MainActivity.handler.postDelayed(MainActivity.runnable, 0);


                }

            }}
    });

//code in main Activity class
  public static Runnable runnable = new Runnable() {

    public void run() {

        MillisecondTime = SystemClock.uptimeMillis() - StartTime;

        UpdateTime = TimeBuff + MillisecondTime;

        Seconds = (int) (UpdateTime / 1000);

        Minutes =1 +( Seconds / 60);

        Hours = Minutes / 60;

        Seconds = Seconds % 60;

        MilliSeconds = (int) (UpdateTime % 1000);

        minuteSum = (Hours * 60) + Minutes;
        minuteSumDaily = (Hours * 60) + Minutes;


        textView.setText("" + Hours + ":"
                + String.format("%02d", Minutes) + ":"
                + String.format("%02d", Seconds));


        handler.postDelayed(this, 0);


    }

};

To answer your question, move your Handler callbacks to a Service. This will keep accurate time even if your user leaves your app to write a text or email or make a call.

However you are trying to run your Runnable continuously , you only need to run it once a second (for example handler.postDelayed(this, 1000); ) but hardcoding 1000 milliseconds will introduce a small error on every execution. You could write a way to check what the offset is and adjust accordingly... but the classes Chronometer and CountDownTimer conveniently already do this for you. You should just switch to using one of those or copy their callback methods.

(Yes, CountDownTimer counts in the wrong direction but just reverse the math.)

Lastly, look into DateUtils.formatElapsedTime() . It takes milliseconds and outputs locale specific "HH:mm:ss".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM