首页 文章

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

提问于
浏览
269

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

  • 用户单击一个按钮(实际上是一张卡片),我通过更改此按钮的背景来显示它:

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

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

10 回答

  • 4

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

    但是,有些人已经指出了上面的解决方案,因为它使用了一个非静态的内部和匿名类,它隐式地保存了对其外部类的引用,即活动 . 当活动上下文被垃圾收集时,这是一个问题 .

    避免内存泄漏的更复杂的解决方案将 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到Activity,这在需要访问UI的静态类中是必需的 .

  • 178

    你可以尝试一下这是 short

    SystemClock.sleep(7000);
    

    WARNING :永远不要在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的问题;)

    Documentation

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

    我用这个:

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

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

    另一种可能性是使用Handler . 关于从使用Timer切换到使用Handler的人有a tutorial .

    顺便说一下,你不能暂停一个过程 . Java(或Android)进程至少有一个线程,您只能睡眠线程 .

  • 4

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

    这就是我在一天结束时所做的 - 现在工作正常:

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

    除了Yankowsky先生的答案,您还可以使用 postDelayed() . 这可以在任何 View (例如,您的卡)上获得,并且需要 Runnable 和延迟期 . 它在延迟之后执行 Runnable .

  • 8

    这是我的榜样

    创建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();  
    
            }
    
        }
    
  • 11

    或者您可以使用:

    android.os.SystemClock.sleep(checkEvery)
    

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

  • 0

    如果你使用Kotlin和coroutines,你可以做到

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

    如果您需要更新UI

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

相关问题