В настоящее время я работаю над приложением 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 (не знаю, какой использовать), но звонки все еще осуществляются.
Есть идеи?
Заранее спасибо!