0

I have a TextView. I want to update its text (append a "1") after 1 second of a button click.

public class HaikuDisplay extends Activity {
    Method m;
    Timer t;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        t = new Timer();
        m = HaikuDisplay.class.getMethod("change");
    }
    //Event handler of the button
    public void onRefresh(View view)
    {       
        //To have the reference of this inside the TimerTask
        final HaikuDisplay hd = this;
        TimerTask task1 = new TimerTask(){
            public void run(){
                /*
                 * I tried to update the text here but since this is not the UI thread, it does not allow to do so.
                 */
                //Calls change() method
                m.invoke(hd, (Object[])null);
            }
        };
        t.schedule(task1, 1000);
    }
    public void change()
    {
        //Appends a "1" to the TextView
        TextView t = (TextView)findViewById(R.id.textView1);
        t.setText(t.getText() + "1");
    }

    //Event handler of another button which updates the text directly by appending "2".
    //This works fine unless I click the first button.
    public void onRefresh1(View view)
    {
        TextView t = (TextView)findViewById(R.id.textView1);
        t.setText(t.getText() + "2");
    }
}

Consider all Exceptions be handled.

On first click, m.invoke gives InvocationTargetException. But it calls the method change() on successive invokes without any Exceptions(verified by logging). But it does not update the text. Where am I wrong?

Also, I see in the debugger that it creates a new Thread every time I click the button. That is fine. But why isn't it removing the previous Threads though their execution has been completed?

Shashwat
  • 2,538
  • 7
  • 37
  • 56

4 Answers4

2
                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        // Update UI

                    }
                }, 1000);

implement this on button click

UPDATE:

There are some other answers. dtmilano suggested another solution which is almost same to mine except he is calling the postDelayed method of View class and In my answer I used postDelayed method of handler class.

from the api reference of android the postDelayed method of Handler says

The runnable will be run on the thread to which this handler is attached.

and the postDelayed method of View says

The runnable will be run on the user interface thread.

This is the only difference between these two solution. in my answer instead of creating new Handler every time you can use any other handler instance. Then the runnable will be run on that thread where that specific handler is declared. And if the postDelayed of EditText is used the the runnable method will be run on the user Interface Thread.

Now the performance issue, both has the same performance (If anybody can prove me wrong with reference I will be happy)

stinepike
  • 54,068
  • 14
  • 92
  • 112
  • One more solution is given by dtmilano. There he had created an `EditText t` and then used `t.postDelayed` instead of the handler. Can you tell me what is the difference between the two? – Shashwat Mar 05 '13 at 09:32
  • Does it enqueue the code inside `run()` to the main UI Thread? Because if it'd have started another Thread, then it won't have allowed me to make those changes. – Shashwat Mar 05 '13 at 09:47
2

Do something like this

public void onRefresh1(View v) {
    // You can have this in a field not to find it every time
    final EditText t = (EditText) findViewById(R.id.textView1);
    t.postDelayed(new Runnable() {

        @Override
        public void run() {
            t.append("1");
        }
    }, 1000);
}
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • One more solution is given by StinePike. There he had used `new Handler().postDelayed`. Can you tell me what is the difference between the two? – Shashwat Mar 05 '13 at 09:31
  • Does it enqueue the code inside `run()` to the main UI Thread? Because if it'd have started another Thread, then it won't have allowed me to make those changes. – Shashwat Mar 05 '13 at 09:45
  • "The runnable will be run on the user interface thread." from http://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long) – Diego Torres Milano Mar 05 '13 at 22:42
1

That's looking awful convoluted - have you considered using CountDownTimer instead?

new CountDownTimer(1000, 1000) {
    public void onTick(long millisUntilFinished) {
        // no-op
    }

    public void onFinish() {
        change();
    }
}.start();

This should call change (and hence change the text) on the UI thread, avoiding reflection and threading errors.

Alex Gilleran
  • 597
  • 3
  • 12
  • Is it creating another Thread or just enqueuing the operation under `onFinish()` to the main UI Thread? – Shashwat Mar 05 '13 at 09:49
0

Hi Use the following code for that. Hope this will help you .

new java.util.Timer().schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
            }
        }, 
        1000 
);

Have a look of this question also.

display data after every 10 seconds in Android

You can try with this also.

private Handler handler = new Handler();    
private Runnable runnable = new Runnable() {   
    public void run() {
        doStuff();
        /*
         * Now register it for running next time
         */
        handler.postDelayed(this, 1000);
    } 
    };




**EDIT 3**



  Try with this once you are need to enable once (i mean if you put your code in yourmethod()== this will get automatically call 1 seconds once. 

    private Timer timer;
    TimerTask refresher;

              // Initialization code in onCreate or similar:

              timer = new Timer();    
              refresher = new TimerTask() {
                  public void run() {
                      yourmethod();
                  };
              };
              // first event immediately,  following after 1 seconds each
              timer.scheduleAtFixedRate(refresher, 0,100); 
Community
  • 1
  • 1
itsrajesh4uguys
  • 4,610
  • 3
  • 20
  • 31