在一段时间后按钮点击更新UI

时间:2013-03-04 05:44:49

标签: android event-handling textview timertask

我有一个TextView。我想在按一下按钮1秒后更新其文本(附加“1”)。

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");
    }
}

考虑处理所有异常。

首次点击时,m.invokeInvocationTargetException。但它在连续调用时调用方法change(),没有任何异常(通过日志记录验证)。但它不会更新文本。我哪里错了?

另外,我在调试器中看到每次单击按钮时它都会创建一个新的Thread。那样就好。但是为什么不删除以前的Threads虽然它们的执行已经完成了?

4 个答案:

答案 0 :(得分:3)

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

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

                    }
                }, 1000);

点击按钮

实现此功能

<强>更新

还有其他一些答案。 dtmilano建议另一个解决方案,除了他调用View类的postDelayed方法之外几乎与我的相同,在我的回答中我使用了postDelayed方法的处理程序类。

来自android的api引用,Handler的postDelayed方法说

  

runnable将在此处理程序所在的线程上运行   附接。

和View的postDelayed方法说

  

runnable将在用户界面线程上运行。

这是这两种解决方案之间的唯一区别。在我的答案中,而不是每次可以使用任何其他处理程序实例时创建新的Handler。然后runnable将在声明该特定处理程序的那个线程上运行。如果使用了postDelayed的EditText,则runnable方法将在用户界面线程上运行。

现在性能问题,都有相同的表现(如果有人可以证明我错了参考我会很高兴)

答案 1 :(得分:2)

做这样的事情

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);
}

答案 2 :(得分:1)

这看起来很糟糕 - 您是否考虑过使用CountDownTimer

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

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

这应该调用UI线程上的更改(从而更改文本),避免反射和线程错误。

答案 3 :(得分:0)

嗨使用以下代码。希望这会帮助你 。

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

也看看这个问题。

display data after every 10 seconds in Android

你也可以试试这个。

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);