Я новичок в Kotlin и в настоящее время разрабатываю приложение для викторины в Android studio . Я получаю вопросы из API ( Открыть базу данных пустяков ). Я использую индикатор выполнения для отображения времени для пользователей, когда они отвечают на вопросы. В настоящее время я использую обратные вызовы, чтобы получить переменные и узнать, когда мои функции завершены. Это мои функции для извлечения данных из API:
private fun fetchTokens(callback: (String)->Unit){
val tokenUrl = "https://opentdb.com/api_token.php?command=request"
var retrieveToken = Request.Builder()
.url(tokenUrl)
.build()
client.newCall(retrieveToken).enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
val gson = GsonBuilder().create()
val triviaRequest = gson.fromJson(body, TriviaResult::class.java)
token = triviaRequest.token
}
})
callback(token)
}
private fun fetchQuestions(aToken: String, callback: ()->Unit){
val theme = intent.getIntExtra("theme", 0)
val difficulty = intent.getStringExtra("difficulty")
val url = "https://opentdb.com/api.php?
amount=10&category=$theme&difficulty=$difficulty&type=multiple&token=$aToken"
val request = Request.Builder()
.url(url)
.build()
client.newCall(request).enqueue(object: Callback {
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
val gson = GsonBuilder().create()
val triviaRequest = gson.fromJson(body, TriviaRequest::class.java)
val result = triviaRequest.results[0]
val question = result.question.toSpanned()
val questionCategory = result.category.toSpanned()
val correctAnswer = result.correct_answer.toSpanned()
val incorrectAnswer1 = result.incorrect_answers[0].toSpanned()
val incorrectAnswer2 = result.incorrect_answers[1].toSpanned()
val incorrectAnswer3 = result.incorrect_answers[2].toSpanned()
val questions = listOf(
correctAnswer,
incorrectAnswer1,
incorrectAnswer2,
incorrectAnswer3
)
shuffle(questions)
runOnUiThread {
val button1 = findViewById<Button>(R.id.alternative1)
val button2 = findViewById<Button>(R.id.alternative2)
val button3 = findViewById<Button>(R.id.alternative3)
val button4 = findViewById<Button>(R.id.alternative4)
questionText.text = question
themeText.text = questionCategory
button1.text = questions[0]
button1.setTextColor(Color.BLACK)
button1.isEnabled = true
button2.text = questions[1]
button2.setTextColor(Color.BLACK)
button2.isEnabled = true
button3.text = questions[2]
button3.setTextColor(Color.BLACK)
button3.isEnabled = true
button4.text = questions[3]
button4.setTextColor(Color.BLACK)
button4.isEnabled = true
button1.setOnClickListener {
button1.isClickable = false
if (button1.text == correctAnswer) {
button1.setTextColor(Color.GREEN)
questionAnswered += 1
score += 1
counter.cancel()
if(questionAnswered == amountOfQuestions){
sendThemeAndDifficultyAndScore(score, theme, difficulty)
finish()
}
startQuizz()
} else {
button1.setTextColor(Color.RED)
}
}
button2.setOnClickListener {
button2.isClickable = false
if (button2.text == correctAnswer) {
button2.setTextColor(Color.GREEN)
questionAnswered += 1
score += 1
counter.cancel()
if(questionAnswered == amountOfQuestions){
sendThemeAndDifficultyAndScore(score, theme, difficulty)
finish()
}
startQuizz()
} else {
button2.setTextColor(Color.RED)
}
}
button3.setOnClickListener {
button3.isClickable = false
if (button3.text == correctAnswer) {
button3.setTextColor(Color.GREEN)
questionAnswered += 1
score += 1
counter.cancel()
if(questionAnswered == amountOfQuestions){
sendThemeAndDifficultyAndScore(score, theme, difficulty)
finish()
}
startQuizz()
} else {
button3.setTextColor(Color.RED)
}
}
button4.setOnClickListener {
button4.isClickable = false
if (button4.text == correctAnswer) {
button4.setTextColor(Color.GREEN)
questionAnswered += 1
score += 1
counter.cancel()
if(questionAnswered == amountOfQuestions){
sendThemeAndDifficultyAndScore(score, theme, difficulty)
finish()
}
startQuizz()
} else {
button4.setTextColor(Color.RED)
}
}
}
}
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
})
callback()
}
А это моя функция для работы с прогрессбаром:
private fun barProgressTimer(){
runOnUiThread {
progressCount = 0
val theme = intent.getIntExtra("theme", 0)
val difficulty = intent.getStringExtra("difficulty")
counter = object : CountDownTimer(millisInFuture.toLong(), countDownInterval.toLong()) {
override fun onFinish() {
questionAnswered += 1
counter.cancel()
if(questionAnswered == amountOfQuestions){
sendThemeAndDifficultyAndScore(score, theme, difficulty)
}
startQuizz()
}
override fun onTick(millisUntilFinished: Long) {
if(progressCount == 101){
counter.onFinish()
} else {
progressBar.progress = progressCount
progressCount++
}
}
}.start()
}
}
Это моя функция для объединения всех функций и затем я вызываю it onCreate :
private fun startQuizz(){
fetchTokens {
token ->
Log.d("tokenInStartQuizz", token)
fetchQuestions(token) {
barProgressTimer()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_answer)
startQuizz()
}
Когда я запускаю этот код, индикатор выполнения запускается примерно за 10 секунд до появления вопросов в пользовательском интерфейсе. Я попытался найти сопрограммы , но мне сейчас трудно понять. Как я могу улучшить этот код, чтобы barprogresstimer запускался, когда fetchQuestions завершил выполнение и обновил пользовательский интерфейс?
Заранее спасибо!