Как остановить выполнение вызовов API - PullRequest
0 голосов
/ 04 марта 2020

В настоящее время я работаю над приложением Quiz в android studio с kotlin. Я получаю вопросы из API. Когда я достигну заданного количества вопросов, я отправлю несколько намерений, затем начну новое действие, подобное этому:

 private fun sendThemeAndDifficultyAndScoreAndToken(score: Int, theme: Int, difficulty: String) {
    val intent = Intent(this, ShowScoreActivity::class.java)
    intent.putExtra("score", score)
    intent.putExtra("theme", theme)
    intent.putExtra("difficulty", difficulty)
    intent.putExtra("token", token)
    startActivity(intent)
    finish()
}

Затем я замечаю, что когда я в новом действии, старое действие все еще выбирает вопросы из API. Я не хочу, чтобы это произошло, потому что у меня есть кнопка повтора, которая возвращает меня к старому действию, а затем она получает двойное значение. Это мои функции для извлечения из API:

private fun fetchTokens(callback: (String)->Unit){
    val tokenUrl = "https://opentdb.com/api_token.php?command=request"
    val retrieveToken = Request.Builder()
        .url(tokenUrl).tag("FetchTokens")
        .build()
    client.newCall(retrieveToken).enqueue(object: Callback {

        override fun onResponse(call: Call, response: Response) {

            Log.d("response", "inside response")
            val body = response.body?.string()
            val gson = GsonBuilder().create()
            val triviaRequest = gson.fromJson(body, TriviaResult::class.java)
            token = triviaRequest.token
            callback(token)
        }

        override fun onFailure(call: Call, e: IOException) {
            e.printStackTrace()
            callback("Error")
        }
    })
}


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=1&category=$theme&difficulty=$difficulty&type=multiple&token=$aToken"
    Log.d("url:", url)
    val request = Request.Builder()
        .url(url).tag("FetchQuestions")
        .build()
    client.newCall(request).enqueue(object: Callback {

        override fun onResponse(call: Call, response: Response) {

            val body = response.body?.string()
            Log.d("body", body)
            val gson = GsonBuilder().create()
            val triviaRequest = gson.fromJson(body, TriviaRequest::class.java)
            val result = triviaRequest.results[0]
            Log.d("result:", result.toString())
            val question = result.question.toSpanned()
            Log.d("question:", question.toString())
            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 alternatives = listOf(
                correctAnswer,
                incorrectAnswer1,
                incorrectAnswer2,
                incorrectAnswer3
            )
            Log.d("questions", alternatives.toString())
            shuffle(alternatives)

            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 = alternatives[0]
                button1.setTextColor(Color.BLACK)
                button1.isEnabled = true

                button2.text = alternatives[1]
                button2.setTextColor(Color.BLACK)
                button2.isEnabled = true

                button3.text = alternatives[2]
                button3.setTextColor(Color.BLACK)
                button3.isEnabled = true

                button4.text = alternatives[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){
                            counter.cancel()
                            sendThemeAndDifficultyAndScoreAndToken(score, theme, difficulty)
                        }
                        fetchQuestions(token){
                            barProgressTimer()
                        }
                    } 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){
                            counter.cancel()
                            sendThemeAndDifficultyAndScoreAndToken(score, theme, difficulty)
                        }
                        fetchQuestions(token){
                            barProgressTimer()
                        }
                    } 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){
                            counter.cancel()
                            sendThemeAndDifficultyAndScoreAndToken(score, theme, difficulty)
                        }

                        fetchQuestions(token){
                            barProgressTimer()
                        }
                    } 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) {
                            counter.cancel()
                            sendThemeAndDifficultyAndScoreAndToken(score, theme, difficulty)
                        }
                        fetchQuestions(token){
                            barProgressTimer()
                        }
                    } else {
                        button4.setTextColor(Color.RED)
                    }
                }
            }
            callback()
        }

        override fun onFailure(call: Call, e: IOException) {
            e.printStackTrace()
        }

    })
}

Это мои onCreate :

 override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_answer)
    val loadBar = findViewById<ProgressBar>(R.id.loadBar)
    Thread(Runnable {
        runOnUiThread {
            loadBar.visibility = View.VISIBLE
        }
        try {
            Thread.sleep(3000)
            startQuiz()
        } catch (e: InterruptedException){
            e.printStackTrace()
        }
        runOnUiThread{
            loadBar.visibility = View.GONE
        }

    }).start()
}

Как я могу предотвратить это? Я знаю, что при переходе к другой активности onPause и onStop будут вызываться для старой активности. Так что, может быть, я могу что-то сделать там, но не знаю что.

РЕДАКТИРОВАТЬ: Я добавил теги к вызовам запроса и сделал эту функцию для отмены вызовов API:

 private fun cancelCallToAPI(){
     for(call : Call in client.dispatcher.runningCalls() ){
         if(call.request().tag()?.equals("FetchQuestions")!!){
             call.cancel()
        }
        if(call.request().tag()?.equals("FetchTokens")!!){
            call.cancel()
        }
     }
     for(call : Call in client.dispatcher.queuedCalls()){
         if(call.request().tag()?.equals("FetchQuestions")!!){
             call.cancel()
         }
         if(call.request().tag()?.equals("FetchTokens")!!){
             call.cancel()
         }
     }
 }

И попытался вызвать это onStop, onPause и onDestroy (не знаю, какой использовать), но звонки все еще осуществляются.
Есть идеи?

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

Ответы [ 2 ]

0 голосов
/ 04 марта 2020

Вы можете остановить запрос FetchQuestion на onDestroy метод

0 голосов
/ 04 марта 2020

Похоже, что вызовы API выполняются из отдельной службы в другом потоке. В вашем коде кажется, что это делается через runuionthread, так как это запускает отдельный поток, который может работать отдельно от действия.

Попробуйте посмотреть этот ответ, чтобы увидеть, как останови это

...