I'm writing an Android quiz app that needs to show a timer. What is the best way to implement the timer? I'm new to android and this is my first app. I tried using Handlers. This works but doesn't seem to be efficient.
public class PertanyaanActivity extends Activity
{
private Handler progressBarHandler = new Handler();
ProgressBar progressBar;
TextView progressText;
PertanyaanData mQuestionData;
JawabanData mAnswerData;
private int mCategoryId;
private Map<Integer, Pertanyaan> mQuestions;
private Map<Integer, Jawaban> mAnswers;
private List<Integer> mQuestionIndexList;
private int mNextQuestionIndex = 0;
private int mTotalQuestions = 0;
private int mQuestionsAnswered = 0;
private int mCorrectAnswers = 0;
private Pertanyaan mCurrentQuestion;
private List<Button> answerButtons;
private LinearLayout.LayoutParams mAnswerButtonLayout;
// private TextView mViewHeader;
private ScrollView mQuestionScrollView;
private TextView mQuestionText;
private LinearLayout mAnswersFrame;
private TextView mQuestionDescriptionText;
// private Button mNextQuestionButton;
// private Button mCompleteButton;
private int max_salah = 0;
private int progressBarStatus = 0;
private long fileSize = 0;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.question);
mCategoryId = getIntent().getIntExtra("categoryId", 0);
Log.i(Constants.APP_LOG_NAME, "Getting question for category ID " + mCategoryId);
mAnswerButtonLayout = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
mAnswerButtonLayout.setMargins(30, 20, 30, 0);
// mViewHeader = (TextView)findViewById(R.id.viewHeader);
mQuestionScrollView = (ScrollView)findViewById(R.id.questionScrollView);
mQuestionText = (TextView)findViewById(R.id.questionText);
mAnswersFrame = (LinearLayout)findViewById(R.id.answersFrame);
progressText=(TextView)findViewById(R.id.progressText);
progressBar= (ProgressBar) findViewById(R.id.ProgressBar01);
// progressBar.setProgress(0);
//progressBar.setMax(100);
waktu();
//mQuestionDescriptionText = (TextView)findViewById(R.id.questionDescriptionText);
// mNextQuestionButton = (Button)findViewById(R.id.nextQuestionButton);
//mCompleteButton = (Button)findViewById(R.id.completeButton);
mQuestionData = new PertanyaanData(this);
mAnswerData = new JawabanData(this);
mQuestions = mQuestionData.getQuestionsByCategoryId(mCategoryId);
mQuestionIndexList = new ArrayList<Integer>();
for (int questionId : mQuestions.keySet())
{
mQuestionIndexList.add(questionId);
}
Collections.shuffle(mQuestionIndexList);
if (mQuestionIndexList.size() > (Constants.MAX_QUESTIONS_PER_ROUND))
{
mQuestionIndexList = mQuestionIndexList.subList(0, Constants.MAX_QUESTIONS_PER_ROUND);
}
mTotalQuestions = mQuestionIndexList.size();
Log.i(Constants.APP_LOG_NAME, "Total questions: " + mTotalQuestions);
if (mTotalQuestions > 0)
{
displayNextQuestion();
}
else
{
Log.e(Constants.APP_LOG_NAME, "No questions found for category ID " + mCategoryId);
}
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
@Override
public void onDestroy()
{
super.onDestroy();
if (mQuestionData != null)
{
mQuestionData.close();
}
if (mAnswerData != null)
{
mAnswerData.close();
}
}
/**
* Displays the next available question in the current trivia round.
*/
public void displayNextQuestion()
{
// Reset ScrollView position.
mQuestionScrollView.scrollTo(0, 0);
waktu();
mCurrentQuestion = getNextQuestion();
String headerText = getString(R.string.question)
+ " " + mNextQuestionIndex
+ " " + getString(R.string.of)
+ " " + mTotalQuestions;
//mViewHeader.setText(headerText);
//nyalakanWaktu();
//waktu();
displayQuestion(mCurrentQuestion);
// mQuestionDescriptionText.setVisibility(View.GONE);
// mNextQuestionButton.setVisibility(View.GONE);
}
/**
* Gets the next available question in the current trivia round.
*
* @return Question - The instance of the next available question.
*/
private Pertanyaan getNextQuestion()
{
int nextQuestionId = mQuestionIndexList.get(mNextQuestionIndex);
Log.i(Constants.APP_LOG_NAME, "Got next question ID " + nextQuestionId);
Pertanyaan question = mQuestions.get(nextQuestionId);
if (question == null)
{
Log.w(Constants.APP_LOG_NAME, "Next question is null.");
}
mNextQuestionIndex++;
return question;
}
/**
* Displays a question on the screen.
*
* @param Question question - The question instance to display.
*/
private void displayQuestion(Pertanyaan question)
{
if (question != null)
{
mAnswers = mAnswerData.getAnswersByQuestionId(question.getPertanyaanId());
List<Integer> answerIndexList = new ArrayList<Integer>();
for (int answerId : mAnswers.keySet())
{
answerIndexList.add(answerId);
}
Collections.shuffle(answerIndexList);
mAnswersFrame.removeAllViews();
mQuestionText.setText(question.getText());
if (mAnswers != null)
{
answerButtons = new ArrayList<Button>();
Jawaban answer = null;
for (int answerId : answerIndexList)
{
Log.i(Constants.APP_LOG_NAME, "Adding answer ID " + answerId);
answer = mAnswers.get(answerId);
Button answerButton = new Button(this);
answerButton.setId(answer.getJawabanId());
answerButton.setText(answer.getText());
answerButton.setBackgroundResource(R.drawable.button_normal);
answerButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
disableAnswerButtons();
answerButtonClickHandler(v);
}
});
answerButtons.add(answerButton);
mAnswersFrame.addView(answerButton, mAnswerButtonLayout);
}
}
}
else
{
// TODO: Need to handle this in a more user-friendly way.
mQuestionText.setText("Null question.");
}
}
/**
* Click handler for answer option buttons.
* Determines the result of the user selecting an answer.
*
* @param View v - The current view.
*/
public void answerButtonClickHandler(View v)
{
Jawaban answer = mAnswers.get(v.getId());
if (answer != null)
{
mQuestionsAnswered++;
if (answer.isCorrect())
{
mCorrectAnswers++;
v.setBackgroundResource(R.drawable.answer_button_correct);
Suara.playButtonClickSuccess();
}
else
{
max_salah++;
v.setBackgroundResource(R.drawable.answer_button_incorrect);
Suara.playButtonClickFailure();
}
// mQuestionDescriptionText.setText(mCurrentQuestion.getDescription());
//mQuestionDescriptionText.setVisibility(View.VISIBLE);
if (mNextQuestionIndex < mQuestionIndexList.size() && max_salah < 3)
{
//mNextQuestionButton.setVisibility(View.VISIBLE);
//nyalakanWaktu();
waktu();
displayNextQuestion();
}
else
{
Intent i = new Intent(this, SummaryActivity.class);
i.putExtra("categoryId", mCategoryId);
i.putExtra("questionsAnswered", mQuestionsAnswered);
i.putExtra("correctAnswers", mCorrectAnswers);
startActivity(i);
//mCompleteButton.setVisibility(View.VISIBLE);
}
}
}
/**
* Click handler for the next question button.
* Displays the next available question after current question is answered.
*
* @param View v - The current view.
*/
public void nextQuestionButtonClickHandler(View v)
{
displayNextQuestion();
Suara.playButtonClick();
}
/**
* Click handler for the trivia round completion button.
* Displays the round summary screen when clicked.
*
* @param View v - The current view.
*/
public void completeButtonClickHandler(View v)
{
Intent i = new Intent(this, SummaryActivity.class);
i.putExtra("categoryId", mCategoryId);
i.putExtra("questionsAnswered", mQuestionsAnswered);
i.putExtra("correctAnswers", mCorrectAnswers);
startActivity(i);
}
/**
* Disables all answer buttons.
* Used after an answer is selected.
*/
private void disableAnswerButtons()
{
Button answerButton = null;
for (int i = 0; i < answerButtons.size(); i++)
{
answerButton = answerButtons.get(i);
answerButton.setEnabled(false);
}
}
public void nyalakanWaktu(){
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
progressBar.incrementProgressBy(1);
int stringProgress=progressBar.getProgress();
progressText.setText(stringProgress+"");
} catch (Exception e) {
}
}
});
}
};timer.schedule(doAsynchronousTask, 0, 200);
//audioBackground.stop();
}
You can use
CountDownTimer
I think its better to use
CountDownTimer
when you have time limit. In above sample 30000 is time limit and has interval of 1000 milliseconds. After 30 minutes theonfinish()
will get called. and you can write your logic for time spent ononTick()
.Better explained here