Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating UI with Runnable & postDelayed not working with timer app

I have looked at every discussion and thread I can find on getting this to work but it is not. I have a simple timer that updates a text view (mTimeTextField in the example below). The mUpdateTimeTask run method is being executed correctly (every second) but the UI/text field is not being updated.

I have code based on the info found here:

http://android-developers.blogspot.com/2007/11/stitch-in-time.html http://developer.android.com/resources/articles/timed-ui-updates.html

Here is the code:

package com.something.handlertest;

import com.something.handlertest.R;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class Test extends Activity {

    private Handler mHandler = new Handler(); 
    private int labelNo    = 0;
    private long currTime  = 0L;
    private long mStartTime = 0L;
    TextView mTimeTextField;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mTimeTextField = (TextView)findViewById(R.id.timeTextFieldl);

        Button startButton = (Button)findViewById(R.id.start_button);
        startButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                   if (mStartTime == 0L) {
                        mStartTime = System.currentTimeMillis();
                        mHandler.removeCallbacks(mUpdateTimeTask);
                        mHandler.postDelayed(mUpdateTimeTask, 100);
                   }
            }
        });
    }

    private Runnable mUpdateTimeTask = new Runnable() {
           public void run() {
               final long start = mStartTime;
               //long millis = SystemClock.uptimeMillis() - start;
               long millis = SystemClock.uptimeMillis();
               int seconds = (int) (millis / 1000);
               int minutes = seconds / 60;
               seconds     = seconds % 60;

               //setContentView(mTimeTextField);  This will blow up if I use it

               if (seconds < 10) {
                   mTimeTextField.setText("" + minutes + ":0" + seconds);
               } else {
                   mTimeTextField.setText("" + minutes + ":" + seconds);            
               }

               //mHandler.postAtTime(this,
                   //    start + (((minutes * 60) + seconds + 1) * 1000));

               mHandler.postAtTime(this, 1000);
           }
        };

}

Per some suggestions, I have tried adding:

setContentView(mTimeLabel);

But this will crash complain about the view not having a parent. FYI, I do have a:

setContentView(R.layout.main);

call in my onCreate().

like image 582
bdelliott Avatar asked Sep 21 '10 23:09

bdelliott


People also ask

Which method is used to set the updates of UI?

Android Thread Updating the UI from a Background Thread The solution is to use the runOnUiThread() method, as it allows you to initiate code execution on the UI thread from a background Thread.

Can we update UI from thread?

Worker threads However, note that you cannot update the UI from any thread other than the UI thread or the "main" thread. To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help: Activity.

What is Post runnable in Android?

post :post causes the Runnable to be added to the message queue, Runnable : Represents a command that can be executed. Often used to run code in a different Thread. run () : Starts executing the active part of the class' code.


2 Answers

Replace

mHandler.postAtTime(this, 1000);

with

mHandler.postDelayed(this, 1000);
like image 190
Fedor Avatar answered Oct 17 '22 07:10

Fedor


  1. You need to do UI updates in the UI thread.
  2. You need to create a Handler in the UI thread to run tasks in the UI thread.

    public class MainActivity extends AppCompatActivity
        private Handler mHandler;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            mHandler = new Handler(); // This to create the Handler in the UI thread
            // ...
        }
    
like image 28
david m lee Avatar answered Oct 17 '22 08:10

david m lee