it-swarm.com.de

Wie mache ich einen Thread oder Prozess in Android?

Ich möchte eine Pause zwischen zwei Codezeilen machen. Lassen Sie mich etwas erklären: 

-> der Benutzer klickt auf eine Schaltfläche (tatsächlich eine Karte) und ich zeige sie durch Ändern des Hintergrunds dieser Schaltfläche: 

thisbutton.setBackgroundResource(R.drawable.icon);

-> Nachdem wir 1 Sekunde gesagt haben, muss ich zum vorherigen Status der Schaltfläche zurückkehren, indem ich den Hintergrund zurückverändere: 

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> Ich habe versucht, den Thread zwischen diesen beiden Codezeilen anzuhalten:

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

Dies funktioniert jedoch nicht. Vielleicht ist es der Prozess und nicht der Thread, den ich pausieren muss?

Ich habe es auch versucht (aber es klappt nicht):

new Reminder(5);

Mit diesem:

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

Wie kann ich den Thread oder Prozess unterbrechen/schlafen?

266
Hubert

Eine Lösung für dieses Problem ist die Verwendung der Methode Handler.postDelayed () . Einige Google Schulungsmaterialien schlagen die gleiche Lösung vor.

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

Einige haben jedoch darauf hingewiesen, dass die Lösung oben einen Speicherverlust verursacht weil sie eine nicht statische innere und anonyme Klasse verwendet, die implizit einen Verweis auf ihre äußere Klasse, die Aktivität, enthält. Dies ist ein Problem, wenn der Aktivitätskontext Müll gesammelt wird. 

Eine komplexere Lösung, die die Speicherverlust-Unterklassen Handler und Runnable mit statischen inneren Klassen innerhalb der Aktivität vermeidet, da statische innere Klassen keinen impliziten Verweis auf ihre äußere Klasse enthalten:

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

Beachten Sie, dass Runnable eine WeakReference für die Activity verwendet, die in einer statischen Klasse erforderlich ist, die Zugriff auf die Benutzeroberfläche benötigt.

427
tronman

Sie können dieses versuchen, es ist kurz 

SystemClock.sleep(7000);

WARNING: Führen Sie dies niemals in einem UI-Thread aus.

Verwenden Sie dies, um zB zu schlafen. Hintergrund-Thread.


Volle Lösung für Ihr Problem wird sein: Dies ist verfügbar 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);
            }
        });

Ohne tmp Handler zu erstellen. Diese Lösung ist auch besser als @tronman, da die Sicht durch Handler nicht beibehalten wird . Außerdem haben wir kein Problem mit Handler, der im fehlerhaften Thread erstellt wurde. 

Dokumentation

öffentlicher statischer void sleep (lange ms)

In API Level 1 hinzugefügt

Wartet eine bestimmte Anzahl von Millisekunden (von uptimeMillis) ab, bevor er zurückkehrt. Ähnlich wie sleep (long), wirft aber keine InterruptedException; Interrupt () -Ereignisse werden bis zum .__ verschoben. nächste unterbrechbare Operation. Gibt nicht zurück, bis mindestens die angegebene Anzahl von Millisekunden abgelaufen ist.

Parameter

ms um vor der Rückkehr in Millisekunden Betriebszeit zu schlafen.

Code für postDelayed from Klasse anzeigen:

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

Ich benutze das:

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

Sie möchten es wahrscheinlich nicht so machen. Durch das Einfügen eines expliziten sleep() in Ihren mit einem Klick versehenen Ereignishandler sperren Sie tatsächlich die gesamte Benutzeroberfläche für eine Sekunde. Eine Alternative ist die Verwendung einer Art Single-Shot Timer . Erstellen Sie eine TimerTask , um die Hintergrundfarbe auf die Standardfarbe zurückzusetzen, und legen Sie sie im Timer fest.

Eine andere Möglichkeit ist die Verwendung eines Handlers . Es gibt ein Tutorial über jemanden, der von einem Timer zu einem Handler gewechselt hat.

Sie können einen Prozess übrigens nicht anhalten. Ein Java- (oder Android-) Prozess hat mindestens einen Thread, und Sie können nur Threads inaktivieren.

16

Ich verwende 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(); 
11
vudandroid

Das habe ich am Ende des Tages getan - funktioniert jetzt gut:

@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
Hubert

Zusätzlich zu den Antworten von Herrn Yankowsky können Sie auch postDelayed() verwenden. Dies ist für jede View (z. B. Ihre Karte) verfügbar und dauert eine Runnable und eine Verzögerungszeit. Nach dieser Verzögerung führt es die Runnable aus.

8
CommonsWare

Das ist mein Beispiel

Erstellen Sie ein Java-Dienstprogramm 

    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
Stefano

Oder du könntest verwenden:

Android.os.SystemClock.sleep(checkEvery)

was den Vorteil hat, dass keine Umhüllung try ... catch erforderlich ist.

4
aaaa

Ich weiß, dass dies ein alter Thread ist, aber in der Android-Dokumentation habe ich eine Lösung gefunden, die für mich sehr gut funktioniert hat ...

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

Hoffe das hilft jemandem ...

0
John Byrne

Wenn Sie Kotlin und Coroutines verwenden, können Sie dies einfach tun

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

Und wenn Sie die Benutzeroberfläche aktualisieren müssen

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