Что-то не так с асинхронными функциями - PullRequest
0 голосов
/ 03 марта 2020

Я новичок в 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 завершил выполнение и обновил пользовательский интерфейс?

Заранее спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...