Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting Two (or More) Functions Simultaneously in Android

I'm in the process of designing a chronometer / countdown timer app for Android 2.2 and would like one button press to start both the chronometer and the timer simultaneously. So, ideally, I'd like the seconds (time) on both the chronometer and timer to change at the same instance. (The timer will be counting down even as the chronometer is counting up). Since I'm using the chronometer and timer functionality provided by Android, I wrote the following piece of code when the user presses the 'Start' button

private boolean mStartPressedOnce = false;
long mTimeWhenStopped = 0;
Chronometer mChronometer;   
MyCounter mCounter;
...
@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.StartButton:
        // Perform some initialization for the chronometer depending
        // on the button press
        if (mStartPressedOnce == false) {
            mChronometer.setBase(SystemClock.elapsedRealtime());
        } else {
            mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped);
        }

        // Perform the initialization for the timer
        mCounter = new MyCount(45000, 1000);

        // Fire up the chronometer  
        mChronometer.start();

        // Fire up the timer
        mCounter.start();
        break;

        case R.id.ResetButton:
            // Reset the chronometer  
            mChronometer.setBase(SystemClock.elapsedRealtime());
            mTimeWhenStopped = 0;
            break;

        case case R.id.StopButton:
            mStartPressedOnce = true;
            // Stop the chronometer 
            mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime();
            mChronometer.stop();
            break;
    }

... 

public class MyCounter extends CountDownTimer {

    @Override
    public MyCount(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onFinish() {        
        // Nothing to do here
    }

    @Override
    public void onTick(long millisUntilFinished) {
        long seconds = (long) (millisUntilFinished / 1000);
        long minutes = (long) ((millisUntilFinished / 1000) / 60);
        long hours = (long) (((millisUntilFinished / 1000) / 60) / 60);

        // Do some formatting to make seconds, minutes and hours look pretty    

        // Update the timer TextView            
       (TextView) findViewById(R.id.CountDownTimerTextView))
           .setText(hours + ":" + minutes + ":" + seconds);
    }
}

Though it looks like the seconds on the chronometer and timer are in sync initially, after a short time, they seem to go off and the second updates for both occur at different times.

Was wondering what I could do to fix this. I did come across - and read this thread

Running multiple AsyncTasks at the same time -- not possible?

I realize that there may be a design change needed but I'm not sure exactly what needs to be done.

Edit: Included types for chronometer and timer and method for calculating time using Chronometer - per jolivier and njzk2's suggestions

like image 302
aLearner Avatar asked Nov 20 '12 12:11

aLearner


People also ask

Can we start two threads at a time?

No. After starting a thread, it can never be started again. If you does so, an IllegalThreadStateException is thrown. In such case, thread will run once but for second time, it will throw exception.

Can multiple processes use the same thread?

The answer is: It depends. On a system with multiple processors or CPU cores (as is common with modern processors), multiple processes or threads can be executed in parallel. On a single processor, though, it is not possible to have processes or threads truly executing at the same time.

Can you call two methods at the same time in Java?

For convenience, Java allows you to write more than one method in the same class definition with the same name. For example, you can have two methods in ShoppingCart class named computeCost. Having two or more methods named the same in the same class is called overloading.


1 Answers

You can retrieve the current time with System.currentTimeMillis(), store it into a variable and forward it to both mChronometer and mCounter, so that they use the same time reference although their task started at different time.

Edit: with the given types, the android documentation about Chronometer will tell you that you can use elapsedRealTime to achieve what I said. CountDownTimer does not have this and its start method is final so you may want to use another implementation, a better view of your use case might help us.

Basically, wanting two threads to perform an action at the same millisecond is never a good idea, one of them will serve as the clock and the other one must be a slave and listen to the clock.

like image 125
jolivier Avatar answered Oct 06 '22 00:10

jolivier