0

私はアンドロイド開発を学んでいます。私がやろうとしているのは、40 分からカウントダウンするラベルを作成することです。ラベルが 0 に達すると、カウントを停止して別のことを行います。これは私のコードです:

@Override
protected void onStart() {
        super.onStart();
        count = 2400;
        final Timer t = new Timer();//Create the object
        t.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                minLeft = (int) Math.floor(count / 60);
                secLeft = count - minLeft * 60;
                counter = minLeft + ":" + secLeft;
                TextView tv = (TextView) findViewById(R.id.timer);

                Log.i(MainActivity.TAG,minLeft+", "+secLeft+", "+counter);
                tv.setText(counter);
                count--;
                if (minLeft <= 0 && secLeft <= 0) {
                    t.cancel();
                    count = 2400;
                    onFinish();
                }
            }
        }, 1000, 1000);
    }

しかし、メインアクティビティのボタンをクリックしてそのアクティビティに移動すると、ラベルに「Timer」というテキスト (元のテキスト) が表示され、数秒後に CalledFromWrongThreadException でアプリがクラッシュしますが、問題の原因となっている行はTextView のテキストを設定する場所になります。

助けてください、事前に感謝します。

4

1 に答える 1

0

スケジュールされたタスクはバックグラウンド スレッドで実行されます。そして、このバックグラウンド スレッドから textview にテキストを設定しようとします。ただし、Android では、ビューに関連するすべての操作をメイン スレッドで実行する必要があります。

スケジュールされたタスクでは、次のようなものを使用する必要があります。

@Override
protected void onStart() {
    super.onStart();
    count = 2400;
    final Timer t = new Timer();//Create the object
    t.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            minLeft = (int) Math.floor(count / 60);
            secLeft = count - minLeft * 60;
            counter = minLeft + ":" + secLeft;
            // the name of your actual activity
            MyActivity.this.runOnUiThread(new Runnable() {
               @Override
               public void run() {
                 TextView tv = (TextView) findViewById(R.id.timer);
                 Log.i(MainActivity.TAG,minLeft+", "+secLeft+", "+counter);
                 tv.setText(counter);
               }
            });

            count--;
            if (minLeft <= 0 && secLeft <= 0) {
                t.cancel();
                count = 2400;
                onFinish();
            }
        }
    }, 1000, 1000);
}

また、このコードは、すべて/非常に多くの匿名クラスを使用せずに、よりエレガントに記述できますが、うまくいくはずです。

于 2014-04-12T16:01:19.177 に答える