Jak ustawić opóźnienie w Androidzie?

164
public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.rollDice:
            Random ranNum = new Random();
            int number = ranNum.nextInt(6) + 1;
            diceNum.setText(""+number);
            sum = sum + number;
            for(i=0;i<8;i++){
                for(j=0;j<8;j++){

                    int value =(Integer)buttons[i][j].getTag();
                    if(value==sum){
                        inew=i;
                        jnew=j;

                        buttons[inew][jnew].setBackgroundColor(Color.BLACK);
                                                //I want to insert a delay here
                        buttons[inew][jnew].setBackgroundColor(Color.WHITE);
                         break;                     
                    }
                }
            }


            break;

        }
    }

Chcę ustawić opóźnienie między poleceniem między zmianą tła. Próbowałem użyć licznika czasu wątku i próbowałem użyć funkcji run and catch. Ale to nie działa. Próbowałem tego

 Thread timer = new Thread() {
            public void run(){
                try {
                                buttons[inew][jnew].setBackgroundColor(Color.BLACK);
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

             }
           };
    timer.start();
   buttons[inew][jnew].setBackgroundColor(Color.WHITE);

Ale zmienia się tylko na czarny.

Kenneth Joseph Paul
źródło

Odpowiedzi:

499

Wypróbuj ten kod:

import android.os.Handler;
...
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 5s = 5000ms
        buttons[inew][jnew].setBackgroundColor(Color.BLACK);
    }
}, 5000);
Tuan Vu
źródło
1
To rozwiązanie wyjaśniło wszystkie pytania, które miałem z programami obsługi w niektórych wierszach kodu.
Sierisimo
45
Zawsze wracam do tego posta, bo jestem zbyt leniwy, żeby za każdym razem go pisać. Dziękuję Ci.
Eugene H,
cóż, jest fajnie, ale mam dużo wiadomości do poczekania, a następnie pokaż. więc różnorodne bieżniki stwarzają problem. jak rozwiązać problem wielu bieżników
mehmet
2
To rozwiązanie powoduje wyciek pamięci, ponieważ używa niestatycznej klasy wewnętrznej i anonimowej, która niejawnie przechowuje odwołanie do swojej klasy zewnętrznej, działania. Zobacz stackoverflow.com/questions/1520887/…, aby znaleźć lepsze rozwiązanie.
tronman
@EugeneH Użyj szablonów Live dla łatwiejszego życia stackoverflow.com/a/16870791/4565796
Saeed Arianmanesh
38

Możesz użyć tego, CountDownTimerco jest znacznie bardziej wydajne niż jakiekolwiek inne opublikowane rozwiązanie. Możesz również generować regularne powiadomienia w odstępach czasu, korzystając z tej onTick(long)metody

Spójrz na ten przykład pokazujący 30-sekundowe odliczanie

   new CountDownTimer(30000, 1000) {
         public void onFinish() {
             // When timer is finished 
             // Execute your code here
     }

     public void onTick(long millisUntilFinished) {
              // millisUntilFinished    The amount of time until finished.
     }
   }.start();
Sufiyan Ghori
źródło
23

Jeśli często używasz opóźnienia w swojej aplikacji, użyj tej klasy narzędzi

import android.os.Handler;


public class Utils {

    // Delay mechanism

    public interface DelayCallback{
        void afterDelay();
    }

    public static void delay(int secs, final DelayCallback delayCallback){
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                delayCallback.afterDelay();
            }
        }, secs * 1000); // afterDelay will be executed after (secs*1000) milliseconds.
    }
}

Stosowanie:

// Call this method directly from java file

int secs = 2; // Delay in seconds

Utils.delay(secs, new Utils.DelayCallback() {
    @Override
    public void afterDelay() {
        // Do something after delay

    }
});
aruke
źródło
1
Czemu ? To czysty narzut i złożoność ... na nic
juloo65
Jeśli używamy częstych opóźnień, posiadanie stałego formatu opóźnień jest w porządku. Nie sądzę, by było dużo narzutów z powodu jednego dodatkowego interfejsu i metody.
aruke
18

Korzystanie z Thread.sleep(millis)metody.

user2270457
źródło
30
nie rób tego w wątku UI - inne elementy również mogą przestać odpowiadać, a później zachowywać się nieprzewidywalnie
Jmaculate
1
dzięki za ostrzeżenie. to jest dokładnie to, czego potrzebuję, aby opóźnić wątek interfejsu użytkownika. doskonała odpowiedź na moje potrzeby. dzięki.
Hamish
7

Jeśli chcesz zrobić coś w interfejsie użytkownika w regularnych odstępach czasu, bardzo dobrą opcją jest użycie CountDownTimer:

new CountDownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();
Ivo Stoyanov
źródło
Jest czystszy niż Handler .
Ahsan,
3

Odpowiedź handlera w Kotlinie:

1 - Utwórz funkcję najwyższego poziomu w pliku (na przykład plik zawierający wszystkie funkcje najwyższego poziomu):

fun delayFunction(function: ()-> Unit, delay: Long) {
    Handler().postDelayed(function, delay)
}

2 - Następnie zadzwoń w dowolne miejsce:

delayFunction({ myDelayedFunction() }, 300)
Phil
źródło
2

Możesz użyć tego:

import java.util.Timer;

a dla samego opóźnienia dodaj:

 new Timer().schedule(
                    new TimerTask(){
                
                        @Override
                        public void run(){
                            
                        //if you need some code to run when the delay expires
                        }
                        
                    }, delay);

gdzie delayzmienna jest w milisekundach; na przykład ustawione delayna 5000 dla 5-sekundowego opóźnienia.

Dror
źródło
0

Oto przykład, w którym zmieniam obraz tła z jednego na drugi z 2-sekundowym opóźnieniem zanikania alfa w obie strony - 2-sekundowe zanikanie oryginalnego obrazu na 2-sekundowe zanikanie na drugim obrazie.

    public void fadeImageFunction(View view) {

    backgroundImage = (ImageView) findViewById(R.id.imageViewBackground);
    backgroundImage.animate().alpha(0f).setDuration(2000);

    // A new thread with a 2-second delay before changing the background image
    new Timer().schedule(
            new TimerTask(){
                @Override
                public void run(){
                    // you cannot touch the UI from another thread. This thread now calls a function on the main thread
                    changeBackgroundImage();
                }
            }, 2000);
   }

// this function runs on the main ui thread
private void changeBackgroundImage(){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            backgroundImage = (ImageView) findViewById(R.id.imageViewBackground);
            backgroundImage.setImageResource(R.drawable.supes);
            backgroundImage.animate().alpha(1f).setDuration(2000);
        }
    });
}
MuharizJ
źródło