如何暂停/睡眠线程或进程在Android?

我想在两行代码之间暂停一下,让我解释一下:

->用户点击一个按钮(事实上是一张卡片),我通过改变这个按钮的背景来显示它:

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
}
}
}

如何暂停/休眠线程或进程?

682479 次浏览

你可能不想这么做。通过在单击按钮的事件处理程序中放入显式sleep(),实际上会将整个UI锁定一秒钟。一种替代方法是使用某种单发计时器。创建一个TimerTask来将背景颜色更改回默认颜色,并在计时器上调度它。

另一种可能性是使用处理程序。有一个教程关于某人谁从使用定时器切换到使用处理程序。

顺便说一句,您不能暂停一个进程。Java(或Android)进程至少有一个线程,并且只能休眠线程。

除了Yankowsky先生的答案,你还可以使用postDelayed()。这适用于任何View(例如,你的卡),并需要Runnable和延迟期。它在该延迟之后执行Runnable

这就是我在一天结束时所做的——现在工作得很好:

@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);
}

这个问题的一个解决方案是使用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);
}

然而,有些人指出导致内存泄漏上面的解决方案,因为它使用了一个非静态的内部匿名类,隐式地保存了对其外部类activity的引用。当活动上下文被垃圾收集时,这是一个问题。

一个更复杂的解决方案,避免内存泄漏的子类HandlerRunnable与活动中的静态内部类,因为静态内部类不持有对它们的外部类的隐式引用:

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引用,这在需要访问UI的静态类中是必要的。

这是我的例子

创建一个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();


}


}

我用这个:

Thread closeActivity = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
// Do some stuff
} catch (Exception e) {
e.getLocalizedMessage();
}
}
});

你可以试试这个,它是

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处理程序。此外,这个解决方案比@tronman更好,因为我们不通过Handler保留视图。 我们也没有在坏线程创建Handler的问题;)

< a href = " http://developer.android.com/reference/android/os/SystemClock.html睡眠% 28长% 29”>文档< / >

公共静态空白睡眠(长毫秒)

在API级别1中添加

在返回之前等待给定毫秒数(uptimeMillis)。类似于sleep(long), 但不会抛出InterruptedException;Interrupt()事件被延迟到 下一个可中断操作。

?

参数

女士在返回之前进入睡眠状态,正常运行时间以毫秒为单位。

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;
}

我使用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();

或者你可以用:

android.os.SystemClock.sleep(checkEvery)

它的优点是不需要包装try ... catch

如果你使用Kotlin和协同程序,你可以简单地做

GlobalScope.launch {
delay(3000) // In ms
//Code after sleep
}

如果你需要更新UI

GlobalScope.launch {
delay(3000)
GlobalScope.launch(Dispatchers.Main) {
//Action on UI thread
}
}

我知道这是一个旧的线程,但在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

希望这能帮助到某人…

  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回答中描述的“静态类”方法结合起来