如何在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个线程,您只能休眠线程。

您可能不想这样做。通过将显式的
sleep()
放在点击按钮的事件处理程序中,实际上可以将整个UI锁定一秒钟。另一种选择是使用某种单发。创建一个将背景颜色更改回默认颜色,并在计时器上安排它

另一种可能性是使用。有人从使用计时器改为使用处理器


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

除了Yankowsky先生的答案之外,您还可以使用
postdayed()
。这在任何
视图
(例如,您的卡)上都可用,并且需要
可运行
和延迟时间。它在延迟后执行
Runnable

除了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);
        // 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的静态类中是必需的。

这个问题的一个解决方案是使用该方法。一些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); 
}
然而,有人指出,上述解决方案是因为它使用了一个非静态的内部匿名类,该类隐式地持有对其外部类activity的引用。当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();  

        }

    }    
这是我的例子

创建一个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();
    }
  }
});
我用这个:

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,通常是因为 *正在退出处理消息队列的循环器。请注意 *真实结果
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);
      }
    }