0

I am trying to make a clock, using a TextView :)

Someone here told me that I couldn't use normal threads to change the UI, but Handler or AsyncTask. I managed to get it working a few days ago, but was not a consistent thread.

Now what I want is a consistent thread that is always changing the text of my Textview. I tried using this, but didn't work, any help?

private void startClock() {
    new Handler().postDelayed(new Runnable(){

        @Override
        public void run() {
            while (true) {
                final long millis = System.currentTimeMillis() - MainActivity.startedAt;
                clock.setText("" + millis);
                runOnUiThread (new Runnable() {

                    @Override
                    public void run() {
                        clock.setText("" + millis);
                    }
                });

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }, 2000);
}
TiagoM
  • 3,458
  • 4
  • 42
  • 83
  • 2
    Why not use the `Timer` class instead? Would make your life much simpler. See here: http://stackoverflow.com/questions/15317600/simple-way-to-update-widget-textview-periodically/15317615#15317615 – Tyler MacDonell Mar 10 '13 at 01:07
  • Thats might be a solution, didnt know about the Timer class, but that is just for one run right? I want a clock always running.. I would need to call multiple times the Timer, and could cause me the same freeze.. thanks for your reply! really appreciated ;) always people helping here :) – TiagoM Mar 10 '13 at 01:35
  • 1
    No, you can schedule repeated runs at regular intervals, and it handles most of the logic for you. – Tyler MacDonell Mar 10 '13 at 01:37
  • How by the way? Just calling it multiple times? like inside a loop? but I cant use while(true), another guy on the accepted answer told me :/ – TiagoM Mar 10 '13 at 01:38
  • You basically just pass the `Timer` a callback function called a `TimerTask` and give it a regular interval to execute the `TimerTask` on. No loops required. Please see the question I linked for more details... – Tyler MacDonell Mar 10 '13 at 01:40
  • Hmm I understood, the Timer repeats the same task until you call the method cancel on the timer, right? This is good too, thanks for the share information :) – TiagoM Mar 10 '13 at 01:48

2 Answers2

4

you should get rid of:

while(true) {
    ....
    sleep(1000);
    ...
}

because this get your thread stuck forever. your program should work like this:

private Handler mHandler = new Handler();

@Override
public void onResume() {
    super.onResume();
    mHandler.removeCallbacks(mUpdateClockTask);
    mHandler.postDelayed(mUpdateCLockTask, 100);
}

@Override
public void onPause() {
    super.onPause();
    mHandler.removeCallbacks(mUpdateClockTask);
}

private Runnable mUpdateClockTask = new Runnable() {
    public void run() {
        updateClock();
        mHandler.postDelayed(mUpdateClockTask, 2000);
    }
};

and inside updateClock() you do all your UI updates.

lenik
  • 23,228
  • 4
  • 34
  • 43
  • I didn't know the while true would cause any problem... I would change that while(true) to a while(toContinue()).. and would check if the activity would be still in use.. and when I would change activity, toContinue() would return false.. Didn't know a while(true) would lag this, but makes sense.. because there are methods like onResume and onPause.. Every time I change activity, but its strange... BECAUSE I didnt even changed activity and it freezed right after... – TiagoM Mar 10 '13 at 01:33
  • Thanks alot anyways lenik, you got my problem fixed, but I would like to understand it, if possible :) – TiagoM Mar 10 '13 at 01:33
  • 1
    first rule of android programming -- never use `while(true)` unless there's a clear exit somewhere inside, that will be triggered really soon. all your functions have to do their job and return back as soon as possible. if something is not ready -- leave it and check again next time you come to the same place. use callbacks from system and/or timers instead of waiting. if there's anything else you want me to explain, please, ask the question, it's a very broad topic to fit into the 500bytes of the comment =) – lenik Mar 10 '13 at 01:38
  • Hey lenik guys like you are very very welcome, thank you so much. You dont need to say twice, I am new to android programming, still learning, have just a few days. But I will not forget, "do not spend time on methods", "use callbacks and timers" . Its enough info for me :) thank you again ;) – TiagoM Mar 10 '13 at 01:41
2

Look here for an example https://stackoverflow.com/a/11140429/808940

Also note that you have a duplicate line in your code:

clock.setText(""+millis);

It appears both in the runOnUiThread and in the main handler, it should only appear in the runOnUiThread runnable

Community
  • 1
  • 1
Moog
  • 10,193
  • 2
  • 40
  • 66
  • 1
    @DarkLink Please don't change the original code after you got an answer like this. I reverted your code. –  Mar 10 '13 at 01:32