我在这个简单的Android代码中缺少什么?

时间:2012-06-14 17:49:04

标签: android multithreading

我试图做其他事情,但继续删除代码,认为简化事情将有助于识别我的错误。这就是我剩下的(经过大量的简化),但我仍然没有得到它为什么它不应该这样做!

public class MyOwnTimerActivity extends Activity {

    int timeLeft = 5;
    TextView timerTextView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button timerButton = (Button) findViewById(R.id.button1);
        timerTextView = (TextView) findViewById(R.id.timerText);

        Thread timer = new Thread() {
            public void run() {
                try {
                    sleep(3000);
                } 
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally{
                    timerTextView.setText("something");
                }
            }
        };
        timer.start();
    }
}

错误:应用程序在3秒后崩溃,即在计时器熄灭后崩溃。

3 个答案:

答案 0 :(得分:4)

啊,是))这是因为您尝试从非UI线程修改UI

更新

有几种方法可以从另一个线程修改UI:

  • 使用Handler类覆盖handleMessage()方法
  • 使用Activity类调用runOnUI()方法,传递Runnable对象,其中run()方法修改了UI
  • 使用View.post()View.postDelayed()方法

    在您的情况下,最后一个变体是最方便的。以这种方式修改您的代码:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button timerButton = (Button) findViewById(R.id.button1);
        timerTextView = (TextView) findViewById(R.id.timerText);
        timerTextView.postDelayed(
            new Runnable() {
               @Override
               run() {
                   timerTextView.setText("something");
               }
            }, 3000);
    }
    
  • 答案 1 :(得分:2)

    您不应该从工作线程更改UI。使用在主线程上初始化的Handler和一个ad-hoc Runnable来在主线程上执行setText()。

    Handler h = new Handler();
    Thread timer = new Thread() { 
    //...
        finally
        {
             h.post(new Runnable(){
                 public void run()
                 {
                     timerTextView.setText("something"); 
                 }
             });
         }
    

    实际上,可以使用Handler.postDelayed()重写整个代码段。但是你最终可能想用一个线程来做更多有趣的事情。

    答案 2 :(得分:0)

    您是否尝试过使用runOnUI从UI线程设置Text?你可以这样做:

    runOnUiThread(new Runnable() { 
        public void run() 
        { 
            timerTextView.setText("something");
        } 
     }); 
    

    请记住,您对timerTextView的引用以及您想要显示的任何文本都必须修改为最终变量,以便从另一个线程引用它。