我想在两行代码之间暂停一下,让我解释一下:
- >用户单击一个按钮(实际上是一张卡片),我通过更改此按钮的背景来显示它:
thisbutton.setBackgroundResource(R.drawable.icon);
- >在让我们说1秒之后,我需要通过改变它的背景来回到按钮的先前状态:
thisbutton.setBackgroundResource(R.drawable.defaultcard);
- >我试图用以下代码暂停这两行代码之间的线程:
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
}
}
}
如何暂停/暂停线程或进程?
答案 0 :(得分:435)
此问题的一个解决方案是使用Handler.postDelayed()方法。一些Google training materials建议采用相同的解决方案。
@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);
}
然而,有些人已经指出上面的解决方案causes a memory leak,因为它使用了一个非静态的内部和匿名类,它隐式地保存了对它的外部类(活动)的引用。当活动上下文被垃圾收集时,这是一个问题。
避免内存泄漏的更复杂的解决方案将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
对活动使用WeakReference,这在需要访问用户界面的静态类中是必需的。
答案 1 :(得分:180)
您可以尝试简短
SystemClock.sleep(7000);
警告:永远不要在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。此解决方案也优于@tronman,因为我们不会保留Handler的视图。 我们也没有在坏线程中创建Handler的问题;)
public static void sleep(long ms)
在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;
}
答案 2 :(得分:24)
我用这个:
Thread closeActivity = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});
答案 3 :(得分:16)
你可能不希望这样做。通过在按钮单击的事件处理程序中放置显式sleep()
,您实际上会锁定整个UI一秒钟。一种选择是使用某种单次Timer。创建TimerTask以将背景颜色更改回默认颜色,并在计时器上安排它。
另一种可能性是使用Handler。有a tutorial关于从使用Timer切换到使用Handler的人。{/ p>
顺便说一下,你不能暂停一个过程。 Java(或Android)进程至少有一个线程,你只能睡眠线程。
答案 4 :(得分:12)
我使用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();
答案 5 :(得分:9)
这就是我在一天结束时所做的 - 现在工作正常:
@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);
}
答案 6 :(得分:8)
除Yankowsky先生的答案外,您还可以使用postDelayed()
。这可以在任何View
(例如,您的卡)上使用,并且需要Runnable
和延迟期。它会在延迟后执行Runnable
。
答案 7 :(得分:4)
这是我的例子
创建Java Utils
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();
}
}
答案 8 :(得分:4)
或者您可以使用:
android.os.SystemClock.sleep(checkEvery)
,其优点是不需要换行try ... catch
。
答案 9 :(得分:0)
如果您使用Kotlin和coroutines,则可以轻松完成
GlobalScope.launch {
delay(3000) // In ms
//Code after sleep
}
如果您需要更新用户界面
GlobalScope.launch {
delay(3000)
GlobalScope.launch(Dispatchers.Main) {
//Action on UI thread
}
}
答案 10 :(得分:0)
我知道这是一个旧线程,但是在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
希望这可以帮助某人...
答案 11 :(得分:0)
class MyActivity{
private final Handler handler = new Handler();
private Runnable yourRunnable;
protected void onCreate(@Nullable Bundle savedInstanceState) {
// ....
this.yourRunnable = new Runnable() {
@Override
public void run() {
//code
}
};
this.handler.postDelayed(this.yourRunnable, 2000);
}
@Override
protected void onDestroy() {
// to avoid memory leaks
this.handler.removeCallbacks(this.yourRunnable);
}
}
请确保您可以将其与tronman答案中所述的“静态类”方法结合使用