user6345865 user6345865 - 6 months ago 107
Java Question

Wait Function not working Android Studio

I am using Android Studio. I am trying to fix a clock in which I pressed the button, it will return the time to 12:00. I got it working but I want it to be executed by waiting 250 miliseconds. The problem is that they only wait for 250 miliseconds (but there are two executions so that's 5 seconds) and then it goes to 12:00 right away without showing it to the Text View. Is there something I am doing wrong? Also if I applied handler function here, I'm afraid I don't have much knowledge to use that.

Edit: This is from my MainActivity method. Example, change from 1 to 2 then wait for 250 miliseconds, change from 2 to 3 then wait for 250 miliseconds

synchronized (this){
try {
while(minuteHand != 0 || hourHand != 12){
if (hourHand != 12){
hourHand++;
hourText.setText(Integer.toString(hourHand));
wait(250);
}
if (minuteHand != 0) {
minuteHand += 5;
minuteHand %= 60;
minuteText.setText(Integer.toString(minuteHand));
wait(250);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Answer

Below is the proper way to update UI elements from an asynchronous thread:

public class SampleActivity extends Activity {
    private TextView hourText;
    private TextView minuteText;

    private void updateHourText(final String text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                hourText.setText(text);
            }
        });
    }

    private void updateMinuteText(final String text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                minuteText.setText(text);
            }
        });
    }

    private class ClockTask extends AsyncTask<Void, Void, Void>
    {
        private int hourHand;
        private int minuteHand;


        public ClockTask(int hourHand, int minuteHand) {
            this.hourHand = hourHand;
            this.minuteHand = minuteHand;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            try {
                while(minuteHand != 0 || hourHand != 12){
                    if (hourHand != 12){
                        hourHand++;
                        updateHourText(Integer.toString(hourHand));
                        Thread.sleep(250);
                    }
                    if (minuteHand != 0) {
                        minuteHand += 5;
                        minuteHand %= 60;
                        updateMinuteText(Integer.toString(minuteHand));
                        Thread.sleep(250);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

And then call this from your button's onClickListener():

new ClockTask(hourHand, minuteHand).execute();

As you can see, in order to update TextView's text, a helper method was needed, which would always execute TextView.setText() inside your main thread. That way, your business logic can execute within its own thread (without causing main thread to wait, which would lead to unresponsive UI), while updating your TextViews asynchronously.

Also, you should never try to update UI elements outside your main thread's context as it will lead to an exception being thrown.

Comments