Jak wstrzymać / uśpić wątek lub proces w Androidzie?

Chcę zrobić pauzę między dwoma linijkami kodu, Pozwól mi trochę wyjaśnić:

- > użytkownik klika przycisk (w rzeczywistości karta) i pokazuję go zmieniając tło tego przycisku:

thisbutton.setBackgroundResource(R.drawable.icon);

-> po powiedzmy 1 sekundzie, muszę wrócić do poprzedniego stanu przycisku zmieniając jego tło:

thisbutton.setBackgroundResource(R.drawable.defaultcard);

- > próbowałem wstrzymać wątek pomiędzy tymi dwoma linijkami kodu:

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

To jednak nie działa. Może to proces, a nie wątek, który muszę pauzować?

Ja też próbowałem (ale nie działa):

new Reminder(5);

Z tym:

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

Jak mogę wstrzymać / uśpić wątek lub proces?

Author: hichris123, 2009-10-05

9 answers

Jednym z rozwiązań tego problemu jest użycie obsługi .metoda postDelayed () . Niektóre materiały szkoleniowe Google sugerują to samo rozwiązanie.

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

Jednak niektórzy zauważyli, że powyższe rozwiązanie powoduje wyciek pamięci , ponieważ używa niestatycznej wewnętrznej i anonimowej klasy, która domyślnie zawiera odniesienie do swojej zewnętrznej klasy, activity. Jest to problem, gdy kontekst aktywności jest zbierany jako śmieci.

Bardziej złożone rozwiązanie, które unikanie podklas wycieku pamięci Handler i Runnable ze statycznymi klasami wewnętrznymi wewnątrz aktywności, ponieważ statyczne klasy wewnętrzne nie zawierają implicit reference do ich zewnętrznej klasy:

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

Zauważ, że Runnable używa WeakReference do aktywności, która jest niezbędna w statycznej klasie, która potrzebuje dostępu do interfejsu użytkownika.

 418
Author: tronman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 20:06:14

Możesz spróbować ten jest krótki

SystemClock.sleep(7000);

WARNING : Nigdy, przenigdy, nie rób tego na wątku UI.

Użyj tego do snu np. wątek w tle.


Pełne rozwiązanie twojego problemu będzie: Jest to dostępne 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);
            }
        });

Bez tworzenia obsługi tmp. Również to rozwiązanie jest lepsze niż @tronman, ponieważ nie zachowujemy widoku przez Handler. Również nie mamy problemu z obsługą utworzoną w złym wątku ;)

Dokumentacja

Public static void sleep (long ms)

Dodany w API poziom 1

Czeka określoną liczbę milisekund (uptimeMillis) przed powrotem. Podobne do sleep (long), ale nie powoduje przerwania ; zdarzenia interrupt() są odraczane do momentu Następna przerywana operacja. Czy nie zwraca dopóki nie upłynie co najmniej określona liczba milisekund.

Parametry

Ms usypiać przed powrotem, w milisekundach uptime.

Kod dla postDelayed from View class:

/**
 * <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;
}
 170
Author: Dawid Drozd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-25 08:54:08

Używam tego:

Thread closeActivity = new Thread(new Runnable() {
  @Override
  public void run() {
    try {
      Thread.sleep(3000);
      // Do some stuff
    } catch (Exception e) {
      e.getLocalizedMessage();
    }
  }
});
 24
Author: Byt3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-26 22:27:43

Prawdopodobnie nie chcesz tego robić w ten sposób. Umieszczając jawną sleep() w obsłudze zdarzenia klikniętego przyciskiem, w rzeczywistości zamkniesz cały interfejs użytkownika na sekundę. Jedną z alternatyw jest użycie pewnego rodzaju timera pojedynczego strzału . Utwórz TimerTask , aby zmienić kolor tła z powrotem na domyślny i zaplanuj go na timerze.

Inną możliwością jest użycie Handlera . Jest tutorial o kimś, kto przełączył się z używania timera na używając opiekuna.

Nawiasem mówiąc, nie można wstrzymać procesu. Proces Java (lub Android) ma co najmniej 1 wątek i można tylko uśpić wątki.

 16
Author: Daniel Yankowsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-05 16:01:52

Używam 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(); 
 10
Author: vudandroid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-24 17:34:01

To właśnie zrobiłem na koniec dnia-działa dobrze teraz:

@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); 
    }
 9
Author: Hubert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-17 05:09:17

Oprócz odpowiedzi pana Jankowskiego, możesz również użyć postDelayed(). Jest on dostępny na każdej View (np. na karcie) i trwa Runnable i okres opóźnienia. Wykonuje Runnable po tym opóźnieniu.

 8
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 07:41:32

Oto mój przykład

Tworzenie 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();  

        }

    }    
 4
Author: Stefano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-25 14:29:23

Lub możesz użyć:

android.os.SystemClock.sleep(checkEvery)

Który ma tę zaletę, że nie wymaga owijania try ... catch.

 1
Author: aaaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-06 19:37:45