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;
}
}
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;
}
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!
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.
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é.