2017-02-21 45 views
11

Mam countDownTimer i jeśli użytkownik nie trafi w gameButton w ciągu 12 sekundy, chcę wywołać metodę gameOver. problem albo otrzymuję grę funtion zwaną instamtly, gdy countDownTimer ma 12, albo timer po prostu odlicza. Więc próbuję użyć metody postDelayed(), aby dać użytkownikowi pełną sekundę, aby nacisnąć przycisk i pozwolić countDownTimerowi na kontynuowanie, ale ponieważ mój kod jest teraz, gra zatrzymuje się na 12 niezależnie.jak poprawnie używać postDelayed() w Androidzie studio?

import android.app.Activity; 
import android.os.CountDownTimer; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 



public class GameScreen extends Activity { 

    private TextView time; 
    private Button start; 
    private Button cancel; 
    private Button gameButton; 
    private CountDownTimer countDownTimer; 
    public static int count = 0; 
    public static int countFail = 0; 

    final Handler handler = new Handler(); 
    final Runnable r = new Runnable() { 
     public void run() { 
      handler.postDelayed(this, 1000); 
      gameOver(); 
     } 
    }; 


    private View.OnClickListener btnClickListener = new View.OnClickListener(){ 

     @Override 
     public void onClick(View v) { 

      switch(v.getId()){ 
       case R.id.start_ID : 
        start(); 
        break; 
       case R.id.cancel : 
        cancel(); 
        break; 
       case R.id.gameButton_ID : 
        gameButton(); 
        break; 
      } 

     } 


    }; 


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


     start = (Button) findViewById(R.id.start_ID); 
     start.setOnClickListener(btnClickListener); 
     cancel = (Button) findViewById(R.id.cancel); 
     cancel.setOnClickListener(btnClickListener); 
     time = (TextView) findViewById(R.id.time); 
     gameButton = (Button) findViewById(R.id.gameButton_ID); 
     gameButton.setOnClickListener(btnClickListener); 


    } 

    public void start(){ 

     time.setText("16"); 
     //this doesnt work and makes app crash when you hit start button 

     countDownTimer = new CountDownTimer(16 * 1000, 1000) { 
      @Override 
      public void onTick(long millsUntilFinished){ 
       time.setText("" + millsUntilFinished/1000); 

       //turns textview string to int 
       int foo = Integer.parseInt(time.getText().toString()); 

       if(time.getText().equals("12")){ 

        r.run(); 

       } 

      } 

      public void onFinish() { 
       time.setText("Done !"); 
      } 
     }; 
     countDownTimer.start(); 
    } 

    private void cancel(){ 
     if(countDownTimer != null){ 
      countDownTimer.cancel(); 
      countDownTimer = null; 
     } 
    } 

    private void gameOver(){ 
     Toast.makeText(getApplicationContext(), "You scored " + count, Toast.LENGTH_SHORT).show(); 
     count = 0; 
     countFail = 0; 
     cancel(); 
    } 

    private void gameButton(){ 

     int foo = Integer.parseInt(time.getText().toString()); 

     if(foo % 2 == 0) { 
      Toast.makeText(getApplicationContext(), "PASS", Toast.LENGTH_SHORT).show(); 
      handler.removeCallbacks(r); 
      ++count; 
     } 

     else{ 
      gameOver(); 
     } 
    } 

} 

Odpowiedz

26

Już prawie użyciu postDelayed(Runnable, long) poprawnie, ale po prostu nie do końca. Spójrzmy na twój Runnable.

final Runnable r = new Runnable() { 
    public void run() { 
     handler.postDelayed(this, 1000); 
     gameOver(); 
    } 
}; 

Kiedy wzywamy r.run(); pierwsza rzecz to będzie zrobić, to powiedzieć handler uruchomić ten sam Runnable po 1000 milisekund, a następnie zadzwonić gameOver(). To, co to faktycznie spowoduje, to twoja metoda gameOver() wywoływana dwa razy: raz od razu, i drugi raz, gdy Handler skończy się czekając 1000 milisekund.

Zamiast tego, należy zmienić Runnable do tego:

final Runnable r = new Runnable() { 
    public void run() { 
     gameOver(); 
    } 
}; 

i nazwać tak:

handler.postDelayed(r, 1000); 

nadzieję, że to pomaga.

+0

Właśnie tego potrzebowałem. Dzięki za złamanie tego po prostu. –