B
B
Bafrektez2016-01-26 23:42:42
Java
Bafrektez, 2016-01-26 23:42:42

How to make TextView work with only one timer?

Good afternoon. The problem is this: there is a timer inherited from CountDownTimer, its value is passed to the TextView. There are also two buttons - start and pause. When you press start again, the timer should restart. It does, but in a very strange way. The TextView receives two or more values ​​at the same time, and it turns out that two or more values ​​are displayed at the same time in one second. How to "kill" the previous timer?

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 
    TextView mTimer;
    ImageButton startButton, pauseButton;
    int timeToEnd = 25000;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        mTimer = (TextView) findViewById(R.id.tv);
        startButton = (ImageButton) findViewById(R.id.startButton);
        pauseButton = (ImageButton) findViewById(R.id.pauseButton);
        startButton.setOnClickListener(this);
        pauseButton.setOnClickListener(this);
    }
 
    @Override
    public void onClick(View v) {
        final TimerClass timer = new TimerClass(timeToEnd, 1000);
        switch (v.getId()) {
            case R.id.startButton:
                startButton.setOnClickListener(this);
                timer.start();
                break;
            case R.id.pauseButton:
                pauseButton.setOnClickListener(this);
                timer.cancel();
        }
    }
 
    public class TimerClass extends CountDownTimer {
        public TimerClass(long milliFuture, long interval) {
            super(milliFuture, interval);
        }
 
        @Override
        public void onTick(long millisUntilFinished) {
            long millis = millisUntilFinished;
            String hhmmss = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
                    TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                    TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
            mTimer.setText(hhmmss);
        }
 
        @Override
        public void onFinish() {
            mTimer.setText("Completed");
        }
    }
 
    public void showSetting() {
        Intent intent = new Intent(this, Prefs.class);
        startActivity(intent);
    }
 
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuItem mi = menu.add(0, 0, 0, "Settings");
        mi.setIntent(new Intent(this, Prefs.class));
        return super.onCreateOptionsMenu(menu);
    }
}

PS I tried the old implementation, this problem is not there, but it does not suit me, since the time must be set from the outside and changed at the request of the user, and not be strictly fixed.
btnStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Dorofeev, 2016-01-27
@Bafrektez

I wouldn't do that if I were you, but okay:
1) Why are you setting the TextView text in the timer? This violates the Demeter principle and abstraction. We just make a variable currentTimein the class interface and create a getter for it:

public class TimerClass extends CountDownTimer {
    public String getCurrentTime() {
        return currentTime;
    }

    private String currentTime;

    public TimerClass(long milliFuture, long interval) {
        super(milliFuture, interval);
    }

    @Override
    public void onTick(long millisUntilFinished) {
        long millis = millisUntilFinished;
        String hhmmss = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
                TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
        currentTime = hhmmss;
    }

    @Override
    public void onFinish() {
        currentTime = "Completed";
    }
}

2) Now in the activity class we create the runTimer () method with the Handler, which will
update the text of our TextView:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    TextView mTimer;
    Button startButton, pauseButton;
    int timeToEnd = 25000;
    final TimerClass timer = new TimerClass(timeToEnd, 1000);

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

        mTimer = (TextView) findViewById(R.id.tv);
        startButton = (Button) findViewById(R.id.startButton);
        pauseButton = (Button) findViewById(R.id.pauseButton);
        startButton.setOnClickListener(this);
        pauseButton.setOnClickListener(this);
        runTimer();
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.startButton:
                startButton.setOnClickListener(this);
                timer.start();
                break;
            case R.id.pauseButton:
                pauseButton.setOnClickListener(this);
                timer.cancel();
        }
    }

    private void runTimer() {


        final Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {

                mTimer.setText(timer.getCurrentTime());
                handler.post(this);
            }
        });
    }

}

Ps
Very skeletal implementation. I would have done differently.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question