studio - Como pausar/dormir thread ou processo no Android?



how to use handler in android (7)

Eu quero fazer uma pausa entre duas linhas de código, deixe-me explicar um pouco:

-> o usuário clica em um botão (um cartão de fato) e eu mostro isso mudando o fundo desse botão:

thisbutton.setBackgroundResource(R.drawable.icon);

-> depois digamos 1 segundo, eu preciso voltar ao estado anterior do botão mudando de volta o seu fundo:

thisbutton.setBackgroundResource(R.drawable.defaultcard);

-> Eu tentei pausar o fio entre essas duas linhas de código com:

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

Entretanto, isso não funciona. Talvez seja o processo e não o Thread que eu preciso fazer uma pausa?

Eu também tentei (mas não funciona):

new Reminder(5);

Com isso:

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

Como posso pausar / dormir o segmento ou processo?

https://src-bin.com


Answer #1

Além das respostas do Sr. Yankowsky, você também pode usar postDelayed() . Isto está disponível em qualquer View (por exemplo, seu cartão) e leva um Runnable e um período de atraso. Ele executa o Runnable após esse atraso.


Answer #2

Este é o meu exemplo

Crie um 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();  

        }

    }    

Answer #3

Eu uso o 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(); 

Answer #4

Isto é o que eu fiz no final do dia - funciona bem agora:

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

Answer #5

Se você usa Kotlin e coroutines , você pode simplesmente fazer

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

E se você precisar atualizar a interface do usuário

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

Answer #6

Uma solução para esse problema é usar o método Handler.postDelayed() . Alguns materiais de treinamento do Google sugerem a mesma solução.

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

No entanto, alguns apontaram que a solução acima causa um vazamento de memória porque ele usa uma classe interna e anônima não estática que implicitamente mantém uma referência à sua classe externa, a atividade. Este é um problema quando o contexto da atividade é coletado como lixo.

Uma solução mais complexa que evita o vazamento de memória subclasse o Handler e o Runnable com classes internas estáticas dentro da atividade, uma vez que as classes internas estáticas não contêm uma referência implícita à sua classe externa:

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

Observe que o Runnable usa uma WeakReference para a Activity, que é necessária em uma classe estática que precisa de acesso à interface do usuário.


Answer #7

Você provavelmente não quer fazer isso dessa maneira. Colocando um sleep() explícito no manipulador de eventos clicado por um botão, você realmente bloquearia toda a UI por um segundo. Uma alternativa é usar algum tipo de Timer disparo único. Crie uma TimerTask para alterar a cor de fundo de volta para a cor padrão e agende-a no Timer.

Outra possibilidade é usar um Handler.postDelayed() . Há um tutorial sobre alguém que mudou de usar um timer para usar um manipulador.

Aliás, você não pode pausar um processo. Um processo Java (ou Android) tem pelo menos um thread e você só pode adormecer threads.





multithreading