web-dev-qa-db-ja.com

Androidテキストビューを更新するタイマー(UI)

ストップウォッチを作成するためにタイマーを使用しています。タイマーは、整数値を増やすことで機能します。次に、textviewを絶えず更新することにより、アクティビティにこの値を表示します。

アクティビティのテキストビューを更新しようとするサービスのコードを次に示します。

protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
        }
    }, 0, 1000);
}

間違ったスレッドでUIを更新することについて何らかのエラーが発生しました。

Textviewを絶えず更新するこのタスクを達成するために、どのようにコードを適合させることができますか?

46
JDS
protected static void startTimer() {
    isTimerRunning = true; 
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            elapsedTime += 1; //increase every sec
            mHandler.obtainMessage(1).sendToTarget();
        }
    }, 0, 1000);
}

public Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
    }
};

上記のコードは動作します...

注:UIコンテンツを変更できるように、メインスレッドでハンドラーを作成する必要があります。

89
Nirav

代わりにHandlerを使用して、X秒ごとにUIを更新する必要があります。以下に例を示す別の質問を示します。 時間遅延のあるタスクを繰り返しますか?

非UIスレッドからUIを更新しようとしているため、アプローチが機能しません。これは許可されていません。

8
inazaruk
StopWatch.time.post(new Runnable() {
    StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});

このコードブロックはHandlerに基づいていますが、独自のHandlerインスタンスを作成する必要はありません。

6
DongXu

TimerTaskはRunnableを実装し、これによりスレッドになります。いくつかの作業を行わずに、メインUIスレッドを別のスレッドから直接更新することはできません。できることの1つは、非同期タスクを使用してタイマーを作成し、UIを更新する更新を1秒ごとに公開することです。

2
Ashterothi

私はStopWatch.timeは、TextViewへの静的またはパブリック参照です。これを行う代わりに、 BroadcastReceiver を実装して、タイマー(別のスレッドから実行される)とTextViewの間で通信する必要があります。

2
John Leehey

次のユーティリティを使用できます。

/**
 * Created by Ofek on 19/08/2015.
 */
public class TaskScheduler extends Handler {
    private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
    public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        postDelayed(runnable, delay);
    }
    public void scheduleAtFixedRate(final Runnable task,final long period) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                task.run();
                postDelayed(this, period);
            }
        };
        tasks.put(task, runnable);
        runnable.run();
    }
    public void stop(Runnable task) {
        Runnable removed = tasks.remove(task);
        if (removed!=null) removeCallbacks(removed);
    }

}

次に、UIスレッドによって実行されるコードのどこでも、次のように使用できます。

TaskScheduler timer = new TaskScheduler();
        timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
            }
        },1000);
2
Ofek Ron

ハンドラーを使用できます。

このコードカウンターを1秒ごとに増やしますおよびshow and updateカウンター値textView.

public class MainActivity extends Activity {


    private Handler handler = new Handler();
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        startTimer();
    }


    int i = 0;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            i++;
            textView.setText("counter:" + i);
            startTimer();
        }
    };

    public void startTimer() {
        handler.postDelayed(runnable, 1000);
    }

    public void cancelTimer() {
        handler.removeCallbacks(runnable);
    }

    @Override
    protected void onStop() {
        super.onStop();
        handler.removeCallbacks(runnable);
    }
}
1
faraz khonsari