我在这个简单的android代码中遗漏了什么?

我在这个简单的android代码中遗漏了什么?,android,multithreading,Android,Multithreading,我试图做一些其他的事情,但一直在删除代码,认为简化一些事情将有助于识别我的错误。这就是我在经过大量简化后剩下的东西,但我仍然不明白为什么它不做它应该做的事情 public class MyOwnTimerActivity extends Activity { int timeLeft = 5; TextView timerTextView; /** Called when the activity is first created. */ @Override

我试图做一些其他的事情,但一直在删除代码,认为简化一些事情将有助于识别我的错误。这就是我在经过大量简化后剩下的东西,但我仍然不明白为什么它不做它应该做的事情

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秒后即计时器关闭后崩溃

是的,这是因为您试图从非UI线程修改UI

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

使用具有重写handleMessage方法的处理程序类 通过调用rununui方法使用Activity类,在其中传递修改UI的Runnable对象 使用View.post或View.postdayed方法

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

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

啊,是的,这是因为您试图从非UI线程修改UI

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

使用具有重写handleMessage方法的处理程序类 通过调用rununui方法使用Activity类,在其中传递修改UI的Runnable对象 使用View.post或View.postdayed方法

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

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

您不应该从工作线程更改UI。使用一个在主线程上初始化的处理程序,使用一个特殊的Runnable在主线程上执行setText

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

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

你不应该从工作线程更改UI。使用一个在主线程上初始化的处理程序,使用一个特殊的Runnable在主线程上执行setText

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

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

你试过使用runOnUI从UI线程设置文本吗?您可以这样做:

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

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

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

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

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

它应该做什么?在计时器关闭后将timerTextView更改为其他变量。它在main.xml中定义了其他内容应用程序崩溃时的错误消息是什么?它应该做什么?在计时器关闭后将timerTextView更改为其他内容。它在main.xml中定义了其他内容应用程序崩溃时的错误消息是什么?@AyushGoyal:同意。不能从后台线程(如正在使用的线程)修改用户界面。请切换到使用AsyncTask,或者使用runOnUiThread,这样就可以在主应用程序线程上完成setText调用。明白了。我不知道…只是知道线程是如何工作的,所以我在胡闹。谢谢。@AyushGoyal:同意。不能从后台线程(如正在使用的线程)修改用户界面。请切换到使用AsyncTask,或者使用runOnUiThread,这样就可以在主应用程序线程上完成setText调用。明白了。我不知道…只是知道线程是如何工作的,所以我在胡闹。非常感谢。