0

我有一个文本视图。我想在单击按钮 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.invoke给出InvocationTargetException. 但是它change()在没有任何异常的情况下连续调用该方法(通过日志记录验证)。但它不会更新文本。我哪里错了?

此外,我在调试器中看到每次单击按钮时都会创建一个新线程。那也行。但是为什么它不删除以前的线程,尽管它们的执行已经完成?

4

4 回答 4

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);
}
于 2013-03-04T08:04:28.657 回答
2
                new Handler().postDelayed(new Runnable() {

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

                    }
                }, 1000);

在按钮点击时实现这个

更新:

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

从 android 的 api 参考 Handler 的 postDelayed 方法说

可运行对象将在附加此处理程序的线程上运行。

并且 View 的 postDelayed 方法说

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

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

现在是性能问题,两者具有相同的性能(如果有人能证明我的参考错误,我会很高兴)

于 2013-03-04T06:24:52.713 回答
1

这看起来非常令人费解-您是否考虑过使用CountDownTimer代替?

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

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

这应该在 UI 线程上调用 change(并因此更改文本),避免反射和线程错误。

于 2013-03-04T05:52:57.270 回答
0

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

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

也看看这个问题。

在Android中每10秒显示一次数据

你也可以试试这个。

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); 
于 2013-03-04T05:56:26.483 回答