2行のコードの間を一時停止したいのですが、少し説明しましょう。
- >ユーザーがボタン(実際にはカード)をクリックすると、このボタンの背景を変更することで表示されます。
thisbutton.setBackgroundResource(R.drawable.icon);
- > 1秒後に、背景を元に戻してボタンの前の状態に戻る必要があります。
thisbutton.setBackgroundResource(R.drawable.defaultcard);
- >この2行のコードの間のスレッドを一時停止しようとしました。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ただし、これは機能しません。一時停止する必要があるのは、プロセスであってスレッドではないのでしょうか。
私も試してみました(しかしそれは動作しません):
new Reminder(5);
これとともに:
public class Reminder {
Timer timer;
public Reminder(int seconds) {
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask {
public void run() {
System.out.format("Time's up!%n");
timer.cancel(); //Terminate the timer thread
}
}
}
スレッドまたはプロセスを一時停止/スリープさせるにはどうすればよいですか?
この問題に対する一つの解決策は Handler.postDelayed() メソッドを使うことです。いくつかのグーグル トレーニング資料 は同じ解決策を提案する。
@Override
public void onClick(View v) {
my_button.setBackgroundResource(R.drawable.icon);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
my_button.setBackgroundResource(R.drawable.defaultcard);
}
}, 2000);
}
しかし、 の上の解決策はメモリリークを起こすと指摘している それは暗黙のうちにその外側のクラスであるアクティビティへの参照を保持している非静的な内側および匿名クラスを使用するため。これは、アクティビティコンテキストがガベージコレクションされている場合に問題になります。
静的な内部クラスはそれらの外部クラスへの暗黙の参照を保持していないので、メモリリークを回避するより複雑な解決策はアクティビティ内の静的な内部クラスでHandler
とRunnable
をサブクラス化します。
private static class MyHandler extends Handler {}
private final MyHandler mHandler = new MyHandler();
public static class MyRunnable implements Runnable {
private final WeakReference<Activity> mActivity;
public MyRunnable(Activity activity) {
mActivity = new WeakReference<>(activity);
}
@Override
public void run() {
Activity activity = mActivity.get();
if (activity != null) {
Button btn = (Button) activity.findViewById(R.id.button);
btn.setBackgroundResource(R.drawable.defaultcard);
}
}
}
private MyRunnable mRunnable = new MyRunnable(this);
public void onClick(View view) {
my_button.setBackgroundResource(R.drawable.icon);
// Execute the Runnable in 2 seconds
mHandler.postDelayed(mRunnable, 2000);
}
Runnable
はActivityに WeakReference を使用していることに注意してください。これはUIへのアクセスを必要とする静的クラスで必要です。
これを試すことができますそれは short です
SystemClock.sleep(7000);
_ warning _ :UIスレッドでは絶対にしないでください。
これを使って眠りましょう。バックグラウンドスレッド.
あなたの問題に対する完全な解決策はのようになります:これは利用可能なAPIです1
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View button) {
button.setBackgroundResource(R.drawable.avatar_dead);
final long changeTime = 1000L;
button.postDelayed(new Runnable() {
@Override
public void run() {
button.setBackgroundResource(R.drawable.avatar_small);
}
}, changeTime);
}
});
Tmp Handlerを作成せずに。 Handlerによる見解を保持していないため、この解決策は@tronmanよりも優れています。また、悪いスレッドで作成されたHandlerには問題ありません。
パブリックスタティックボイドスリープ(長ミリ秒)
APIレベル1で追加
戻る前に、指定されたミリ秒数(uptimeMillis)待機します。 sleep(long)と同様に、 ですがInterruptedExceptionをスローしません ; interrupt()イベントは、次の割り込み可能な操作まで延期されます。 指定されたミリ秒数が経過するまで を返しません。
パラメーター
ms 戻る前にスリープ状態になるまでの時間(ミリ秒)。
Viewクラスからの postDelayed のコード:
/**
* <p>Causes the Runnable to be added to the message queue, to be run
* after the specified amount of time elapses.
* The runnable will be run on the user interface thread.</p>
*
* @param action The Runnable that will be executed.
* @param delayMillis The delay (in milliseconds) until the Runnable
* will be executed.
*
* @return true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed --
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*
* @see #post
* @see #removeCallbacks
*/
public boolean postDelayed(Runnable action, long delayMillis) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.postDelayed(action, delayMillis);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
return true;
}
私はこれを使う:
Thread closeActivity = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});
あなたはおそらくそのようにしたくないでしょう。ボタンをクリックしたイベントハンドラに明示的なsleep()
を設定すると、実際にはUI全体が1秒間ロックされます。 1つの選択肢は、ある種のシングルショット タイマー を使うことです。 TimerTask を作成して背景色をデフォルトの色に戻し、タイマーでスケジュールします。
もう一つの可能性は ハンドラ を使うことです。 チュートリアル Timerを使うことからHandlerを使うことに切り替えた人についての/があります。
ちなみに、あなたはプロセスを一時停止することはできません。 Java(またはAndroid)プロセスには少なくとも1つのスレッドがあり、スリープできるのはスレッドだけです。
CountDownTimeを使います
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// do something after 1s
}
@Override
public void onFinish() {
// do something end times 5s
}
}.start();
これは私が一日の終わりにしたことです - 今うまく働きます:
@Override
public void onClick(View v) {
my_button.setBackgroundResource(R.drawable.icon);
// SLEEP 2 SECONDS HERE ...
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
my_button.setBackgroundResource(R.drawable.defaultcard);
}
});
}
}, 2000);
}
ヤンコフスキー氏の答えに加えて、postDelayed()
を使うこともできます。これはどのView
(例えばあなたのカード)でも利用でき、Runnable
と遅延期間がかかります。その遅延後にRunnable
が実行されます。
これは私の例です
Java Utilを作成する
import Android.app.ProgressDialog;
import Android.content.Context;
import Android.content.Intent;
public class Utils {
public static void showDummyWaitingDialog(final Context context, final Intent startingIntent) {
// ...
final ProgressDialog progressDialog = ProgressDialog.show(context, "Please wait...", "Loading data ...", true);
new Thread() {
public void run() {
try{
// Do some work here
sleep(5000);
} catch (Exception e) {
}
// start next intent
new Thread() {
public void run() {
// Dismiss the Dialog
progressDialog.dismiss();
// start selected activity
if ( startingIntent != null) context.startActivity(startingIntent);
}
}.start();
}
}.start();
}
}
またはあなたが使用することができます:
Android.os.SystemClock.sleep(checkEvery)
これはtry ... catch
をラッピングする必要がないという利点があります。
私はこれが古いスレッドであることを知っています、しかしAndroidのドキュメンテーションで私は私のために非常にうまくいった解決策を見つけました...
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
https://developer.Android.com/reference/Android/os/CountDownTimer.html
これが誰かに役立つことを願っています...
Kotlinと コルーチン を使えば、簡単にできます。
GlobalScope.launch {
delay(3000) // In ms
//Code after sleep
}
そしてあなたがUIを更新する必要があるなら
GlobalScope.launch {
delay(3000)
GlobalScope.launch(Dispatchers.Main) {
//Action on UI thread
}
}