1

私は何か他のことをしようとしていましたが、物事を単純化することが私の間違いを特定するのに役立つと考えて、コードを削除し続けました. これは私が残したものです(多くの単純化の後)、それでも私はそれがなぜそれをしていないのか理解していません!

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 秒後、つまりタイマーが切れた後にクラッシュしました。

4

3 に答える 3

4

ああ、はい)) これは、非 UI スレッドから UI を変更しようとするためです。

アップデート:

別のスレッドから UI を変更するには、いくつかの方法があります。

  • HandlerオーバーライドhandleMessage()メソッド でクラスを使用する
  • Activity呼び出しメソッドでクラスを使用し、 UI を変更するメソッド のオブジェクトrunOnUI()をそこに渡しますRunnablerun()
  • 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);
    }
    
  • 于 2012-06-14T17:52:32.030 に答える
    2

    ワーカー スレッドから UI を変更することは想定されていません。メイン スレッドで初期化されたハンドラをアドホック Runnable と共に使用して、メイン スレッドで setText() を実行します。

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

    実際、スニペット全体は Handler.postDelayed() を使用して書き換えることができます。しかし、最終的にはスレッドでもっと面白いことをしたくなるでしょう。

    于 2012-06-14T17:53:18.327 に答える
    0

    runOnUI を使用して UI スレッドから Text を設定しようとしましたか? 次のように行うことができます。

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

    timerTextView への参照と、表示するテキストは、別のスレッドから参照するために最終変数として変更する必要があることに注意してください。

    于 2012-06-14T17:54:55.867 に答える