Hoe kan ik een thread pauzeren/slapen of verwerken in Android?

Ik wil een pauze maken tussen twee regels code, ik zal het even uitleggen:

-> de gebruiker klikt op een knop (in feite een kaart) en ik laat het zien door de achtergrond van deze knop te veranderen:

thisbutton.setBackgroundResource(R.drawable.icon);

-> na laten we zeggen 1 seconde, moet ik teruggaan naar de vorige staat van de knop door de achtergrond terug te veranderen:

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> Ik heb geprobeerd de draad tussen deze twee regels code te pauzeren met:

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

Dit werkt echter niet. Misschien is het het proces en niet de thread die ik moet pauzeren?

Ik heb ook geprobeerd (maar het werkt niet):

new Reminder(5);

Hiermee:

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

Hoe kan ik de thread of het proces pauzeren/slapen?


Antwoord 1, autoriteit 100%

Eén oplossing voor dit probleem is het gebruik van de handler.postdelayed () Methode. Sommige Google trainingsmaterialen suggereren dezelfde oplossing.

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

Sommigen hebben er echter op gewezen dat de oplossing boven Veroorzaakt een geheugenlek omdat het een niet-statische binnen- en anonieme klasse gebruikt die impliciet een verwijzing heeft op de buitenklasse, de activiteit. Dit is een probleem wanneer de activiteitscontext afval is verzameld.

Een complexere oplossing die het geheugenlek vermijdt subclasses de Handleren Runnablemet statische binnenklassen in de activiteit sinds statische binnenklassen geen impliciete verwijzing naar hun Buitenklasse:

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

Merk op dat de Runnableeen WeakReference gebruikt naar de activiteit, die nodig is in een statische klasse die toegang tot de gebruikersinterface nodig heeft.


Antwoord 2, autoriteit 42%

Je kunt deze proberen, hij is kort

SystemClock.sleep(7000);

WAARSCHUWING: doe dit nooit, maar dan ook nooit in een UI-thread.

Gebruik dit om bijv. te slapen. achtergronddraad.


Volledige oplossing voor uw probleem is:
Dit is beschikbaar 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);
            }
        });

Zonder tmp Handler aan te maken. Ook deze oplossing is beter dan @tronman omdat we geen zicht van Handler behouden.
We hebben ook geen probleem met Handler die is gemaakt in een slechte thread 😉

Documentatie

openbare statische slaapstand (lange ms)

Toegevoegd in API-niveau 1

Wacht een bepaald aantal milliseconden (uptimeMillis) voordat hij terugkeert. Gelijk aan sleep(long), maar geeft geen InterruptedException; interrupt() gebeurtenissen worden uitgesteld tot de
volgende onderbreekbare bewerking.
Keert niet terugtotdat ten minste het opgegeven aantal milliseconden is verstreken.

Parameters

msom te slapen voordat je terugkeert, in milliseconden uptime.

Code voor postDelayedvan View klas:

/**
 * <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;
}

Antwoord 3, autoriteit 7%

Ik gebruik dit:

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

Antwoord 4, autoriteit 4%

Ik gebruik 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(); 

Antwoord 5, autoriteit 3%

Je wilt het waarschijnlijk niet op die manier doen. Door een expliciete sleep()in je event-handler met een klik op de knop te plaatsen, zou je eigenlijk de hele gebruikersinterface voor een seconde op slot doen. Een alternatief is om een soort single-shot Timerte gebruiken. Maak een TimerTaskom de achtergrondkleur terug te zetten naar de standaardkleur en plan het op de Timer.

Een andere mogelijkheid is om een Handlerte gebruiken. Er is een tutorialover iemand die is overgestapt van het gebruik van een timer om een handler te gebruiken.

Overigens kun je een proces niet pauzeren. Een Java- (of Android)-proces heeft minimaal 1 thread en u kunt alleen threads in de slaapstand zetten.


Antwoord 6, autoriteit 2%

Dit is wat ik aan het eind van de dag deed – werkt nu prima :

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

Antwoord 7, autoriteit 2%

Naast de antwoorden van Mr. Yankowsky, kunt u ook postDelayed()gebruiken. Dit is beschikbaar op elke View(bijv. uw kaart) en duurt een Runnableen een vertragingsperiode. Het voert de Runnableuit na die vertraging.


Antwoord 8

Dit is mijn voorbeeld

Maak een Java-hulpprogramma

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

Antwoord 9

Of je zou kunnen gebruiken:

android.os.SystemClock.sleep(checkEvery)

wat het voordeel heeft dat er geen verpakking nodig is try ... catch.


Antwoord 10

Ik weet dat dit een oude thread is, maar in de Android-documentatie vond ik een oplossing die heel goed voor mij werkte…

new CountDownTimer(30000, 1000) {
    public void onTick(long millisUntilFinished) {
        mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
    }
    public void onFinish() {
        mTextField.setText("done!");
    }
}.start();

https://developer.android.com/reference/android/os /Countdowntimer.html

Ik hoop dat dit iemand helpt …


Antwoord 11

Als u kotlin en coroutines gebruikt, kunt u eenvoudig

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

en als u UI

moet bijwerken

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

Antwoord 12

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

en om het dubbele te zijn, kunt u deze worden gecombineerd met de “statische klasse” -methode zoals beschreven in het antwoord van TRONMAN

Other episodes