如何在Android中暂停/睡眠线程或进程?
我想在两行代码之间稍作停顿,让我解释一下: ->用户单击一个按钮(实际上是一张卡),我通过更改此按钮的背景来显示它:如何在Android中暂停/睡眠线程或进程?,android,process,multithreading,Android,Process,Multithreading,我想在两行代码之间稍作停顿,让我解释一下: ->用户单击一个按钮(实际上是一张卡),我通过更改此按钮的背景来显示它: thisbutton.setBackgroundResource(R.drawable.icon); ->比方说1秒钟后,我需要通过更改按钮的背景回到按钮的前一个状态: thisbutton.setBackgroundResource(R.drawable.defaultcard); ->我尝试使用以下命令在这两行代码之间暂停线程: try { Thread.slee
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();
}
然而,这是行不通的。也许我需要暂停的是过程而不是线程
我也试过(但不起作用):
为此:
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
}
}
}
如何暂停/休眠线程或进程?您可能不想这样做。通过将显式的
sleep()
放在点击按钮的事件处理程序中,实际上可以将整个UI锁定一秒钟。另一种选择是使用某种单发。创建一个将背景颜色更改回默认颜色,并在计时器上安排它
另一种可能性是使用。有人从使用计时器改为使用处理器
顺便说一句,您不能暂停进程。Java(或Android)进程至少有1个线程,您只能休眠线程。除了Yankowsky先生的答案之外,您还可以使用
postdayed()
。这在任何视图
(例如,您的卡)上都可用,并且需要可运行
和延迟时间。在延迟之后,它执行可运行的。这就是我在一天结束时所做的-现在可以正常工作了:
@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);
}
解决这个问题的一个办法是使用这种方法。一些谷歌提出了同样的解决方案
@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的引用。当活动上下文被垃圾收集时,这是一个问题
一个更复杂的解决方案可以避免内存泄漏,它将处理程序
和可运行
子类化为活动内部的静态内部类,因为静态内部类不包含对其外部类的隐式引用:
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);
}
私有静态类MyHandler扩展处理程序{}
私有最终MyHandler mHandler=新MyHandler();
公共静态类MyRunnable实现Runnable{
对活动的私有最终WeakReference,这在需要访问UI的静态类中是必需的。这是我的示例
创建一个Javautils
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,因为我们不保留处理程序的视图。
此外,在坏线程中创建的处理程序也没有问题;)
公共静态无效睡眠(长毫秒)
在API级别1中添加
在返回之前等待给定的毫秒数(UptimeMills)。与sleep(long)类似,但不会引发InterruptedException;中断()事件将延迟到
下一个可中断操作。
至少经过指定的毫秒数后,才会返回
参数
ms返回前睡眠,以毫秒为单位
“从视图”类的代码:
/**
* <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;
}
/**
*导致将Runnable添加到消息队列中,以便运行
*经过指定的时间后。
*runnable将在用户界面线程上运行
*
*@param action将要执行的可运行操作。
*@param delayMilli延迟(以毫秒为单位),直到可运行
*将被执行。
*
*@return true,如果Runnable成功放置到
*消息队列。失败时返回false,通常是因为
*正在退出处理消息队列的循环器。请注意
*结果为true并不意味着将处理Runnable--
*如果循环器在消息传递时间之前退出
*发生,则消息将被删除。
*
*@see#post
*@see#移除回调
*/
公共布尔postDelayed(可运行操作,长延迟毫秒){
最终附件fo AttachInfo=mAttachInfo;
if(attachInfo!=null){
返回attachInfo.mHandler.postDelayed(操作,延迟毫秒);
}
//假设该职位稍后会成功
ViewRootImpl.getRunQueue().postDelayed(操作,延迟毫秒);
返回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
}
如果你需要更新用户界面
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();
希望这对某人有帮助
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答案中描述的“静态类”方法结合起来噢,只需使用经典的线程暂停块:while(true){}@KristoferA-Huagati.com我不确定你是在挖苦人,还是确实有Dalvik/Android的魔力,所以这在Android上是可以接受的。你能澄清一下吗?很抱歉,我怀疑,但我问你,因为虽然(!conditionCheck()){}
通常不被鼓励。“但是,这不起作用。”“我也尝试过(但不起作用)”这是一个典型的例子,说明在没有给出症状的情况下出现了问题。这些尝试以什么方式未能满足您的要求?线程没有暂停吗?您收到错误消息了吗?它是有效的,但这是一种在整个代码中引入延迟的非常不方便的方式,对吗?我不确定您所说的“不方便”是什么意思.处理程序的postDelayed方法旨在告诉Andro
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);
}
}