web-dev-qa-db-fra.com

Android - boucle du code toutes les 5 secondes

Je voudrais commencer à répéter deux lignes de code toutes les 5 secondes lorsque j'appuie sur le bouton START et le termine lorsque j'appuie sur le bouton STOP. Je trynigrais avec une TimerTask et des poignées, mais je ne comprenais pas comment. 

public class MainActivity extends Activity {




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


           //final int i;
           final TextView textView = (TextView) findViewById(R.id.textView);
           final Button START_STOP = (Button) findViewById(R.id.START_STOP);
           final ImageView random_note = (ImageView) findViewById(R.id.random_note);
           final int min = 0;
           final int max = 2;
           final Integer[] image = { R.drawable.a0, R.drawable.a1,R.drawable.a2 };



        START_STOP.setTag(1);
        START_STOP.setText("START");


        START_STOP.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
            int status = (Integer) v.getTag();
            if (status ==1) {
                textView.setText("Hello");
                START_STOP.setText("STOP");
                v.setTag(0);

                final Random random = new Random();

                                //************************************************************
                // I would like to loop next 2 lines of code every 5 seconds.//

                                int i = random.nextInt(2 - 0 + 1) + 0;
                random_note.setImageResource(image[i]);

                //************************************************************
                    }

            else
            {
                textView.setText("Bye");
                START_STOP.setText("Let's PLAY!");
                v.setTag(1);
            }


            }
        });     

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


}
7
Damijan

Utiliser un compte à rebours comme dans l'une des autres réponses est un moyen de le faire. Une autre solution consisterait à utiliser un gestionnaire et la méthode postDelayed :

private boolean started = false;
private Handler handler = new Handler();

private Runnable runnable = new Runnable() {        
    @Override
    public void run() {
        final Random random = new Random();
        int i = random.nextInt(2 - 0 + 1) + 0;
        random_note.setImageResource(image[i]);
        if(started) {
            start();
        }
    }
};

public void stop() {
    started = false;
    handler.removeCallbacks(runnable);
}

public void start() {
    started = true;
    handler.postDelayed(runnable, 2000);        
}

Voici un exemple utilisant une minuterie et une tâche de minuterie:

private Timer timer;
private TimerTask timerTask = new TimerTask() {

    @Override
    public void run() {
        final Random random = new Random();
        int i = random.nextInt(2 - 0 + 1) + 0;
        random_note.setImageResource(image[i]);
    }
};

public void start() {
    if(timer != null) {
        return;
    }
    timer = new Timer();
    timer.scheduleAtFixedRate(timerTask, 0, 2000);
}

public void stop() {
    timer.cancel();
    timer = null;
}
24
britzl

Vous pouvez utiliser CountDownTimer comme méthode suivante:

private CountDownTimer timer;

timer = new CountDownTimer(5000, 20) {

    @Override
    public void onTick(long millisUntilFinished) {

    }

    @Override
    public void onFinish() {
        try{
            yourMethod();
        }catch(Exception e){
            Log.e("Error", "Error: " + e.toString());
        }
    }
}.start();

Et puis pour rappeler le chronomètre:

public void yourMethod(){
    //do what you want
    timer.start();
}

Pour annuler le chronomètre, vous pouvez appeler timer.cancel();

J'espère que ça aide!

13
Giacomoni

Vous pouvez utiliser RxJava2/RxAndroid2 et créer un observable qui émet un message toutes les secondes (ou ce que vous voulez), par exemple avec un pseudo-code:

Disposable timer = Observable.interval(1000L, TimeUnit.MILLISECONDS)
            .timeInterval()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Timed<Long>>() {
                @Override
                public void accept(@NonNull Timed<Long> longTimed) throws Exception {               
                    //your code here.
                    Log.d(TAG, new DateTime());
                }
            });

Lorsque vous voulez l'arrêter, vous pouvez simplement appeler:

timer.dispose();

Je trouve ce code beaucoup plus lisible que les autres options.

5
db80

Je n'ai pas grand chose à ajouter, mis à part les différences entre Handler, CountDownTimer et Timer normal. Comme mentionné par britzl, CountDownTimer utilise un gestionnaire en interne, ce qui revient à utiliser directement le gestionnaire. Un gestionnaire est utilisé pour exécuter des éléments d'interface utilisateur pendant de très courtes périodes. Un exemple serait setText pour une vue texte. Pour les tâches de calcul intensif, les gestionnaires peuvent entraîner un décalage. Un minuteur ne peut également exécuter que des tâches courtes, mais ce n'est pas nécessairement uniquement pour les éléments d'interface utilisateur. Pour les tâches plus complexes, un nouveau thread doit être utilisé.

0
Walter Morawa