如何在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 } } }
我怎样才能暂停/休眠线程或进程?
解决这个问题的一个办法是使用Handler.postDelayed()方法。 一些Google 培训材料提出了相同的解决方案。
@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
对活动使用WeakReference ,这在需要访问UI的静态类中是必需的。
你可以尝试这个短
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的视图。 此外,我们没有处理程序创建坏线程的问题;)
文档
public static void sleep(long ms)
在API级别1中添加
在返回之前等待给定的毫秒数(uptimeMillis)。 类似于sleep(long), 但不抛出InterruptedException ; 中断()事件被推迟到下一个可中断操作。 直到至少达到指定的毫秒数才会返回 。
参数
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一秒钟。 另一种方法是使用某种单次计时器 。 创建一个TimerTask将背景颜色更改为默认颜色,并将其安排在Timer上。
另一种可能是使用Handler 。 有一个关于从使用定时器切换到使用处理程序的人的教程 。
顺便说一句,你不能暂停一个进程。 Java(或Android)进程至少有一个线程,并且只能休眠线程。
这是我在一天结束时所做的 – 现在正常工作:
@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); }
除了Yankowsky先生的回答之外,您还可以使用postDelayed()
。 这在任何View
(例如,你的卡)上都可用,并且需要一个Runnable
和一个延迟期。 它在延迟之后执行Runnable
。
我使用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();
这是我的例子
创建一个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(); } }