Класс не возвращает объект MutableMap

Я использовал Kotlin, чтобы создать базовое приложение-конвертер валют с API. Чтобы загрузить информацию, я создал новый класс DownloadTaskClass, расширяющий устаревший класс AsyncTask (я не изучал другие классы пакета java.util.concurrent).

DownloadTaskClass содержит метод для возврата MutableMap в MainActivity. Однако я не могу понять, почему этот метод не возвращает объект MutableMap. Вот классы.

Скачать TaskClass.kt

package com.example.kotlincurrency

import android.os.AsyncTask
import org.json.JSONObject
import java.io.InputStream
import java.io.InputStreamReader
import java.lang.Exception
import java.net.HttpURLConnection
import java.net.URL

class DownloadTaskClass: AsyncTask<String, Void, String>() {

    private var data: Int = 0
    private var result: String = ""
    private var mutableMap: MutableMap<String, Any> = mutableMapOf()

    private lateinit var url: URL
    private lateinit var inputStream: InputStream
    private lateinit var inputStreamReader: InputStreamReader
    private lateinit var httpURLConnection: HttpURLConnection

    override fun doInBackground(vararg urls: String): String? {
        url = URL(urls[0])
        httpURLConnection = url.openConnection() as HttpURLConnection
        inputStream = httpURLConnection.inputStream
        inputStreamReader = InputStreamReader(inputStream)
        data = inputStreamReader.read()

        while (data != -1){
            val current: Char = data.toChar()
            result += current
            data = inputStreamReader.read()
        }

        return result
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)

        try {
            val jsonObject = JSONObject(result)
            mutableMap["date"] = jsonObject.getString("date")
            
            val rates: String = jsonObject.getString("rates")
            val currencyJSONObject = JSONObject(rates)
            mutableMap["USD"] = currencyJSONObject.getString("USD")
            mutableMap["GBP"] = currencyJSONObject.getString("GBP")
            mutableMap["EUR"] = currencyJSONObject.getString("EUR")
            mutableMap["CHF"] = currencyJSONObject.getString("CHF")
            mutableMap["SEK"] = currencyJSONObject.getString("SEK")
            mutableMap["CAD"] = currencyJSONObject.getString("CAD")
        }

        catch (e: Exception){
            e.printStackTrace()
        }
    }

    fun returnMapMethod(): MutableMap<String, Any>{
        return mutableMap
    }
}

MainActivity.kt

package com.example.kotlincurrency

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.ActionBar

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setActionBar()
        downloadInitInfo()
    }

    private fun setActionBar() {
        supportActionBar!!.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
        supportActionBar!!.setDisplayShowCustomEnabled(true)
        supportActionBar!!.setCustomView(R.layout.layout_action_bar)
    }

    private fun downloadInitInfo(){
        val downloadTaskClass = DownloadTaskClass()
        downloadTaskClass.execute("https://api.exchangeratesapi.io/latest?base=INR")
        println(downloadTaskClass.returnMapMethod())
    }
}

1 ответ

Решение

Вы делаете асинхронный запрос в doInBackground() метод, это может занять некоторое время, прежде чем onPostExecute() называется и mutableMapзаполнен данными. Когда ты звонишьreturnMapMethod() метод mutableMapобъект еще не заполнен данными. Вам нужно использовать какой-нибудь слушатель, чтобы получать уведомления о загрузке данных.

Вот пример использования LiveData для наблюдения данных:

class DownloadTaskClass: AsyncTask<String, Void, String>() {
    
    private var data: MutableLiveData<MutableMap<String, Any>> = MutableLiveData()

    // ...
    
    override fun onPostExecute(result: String?) {
        // ...
        data.value = mutableMap
    }

    fun returnMapMethod(): LiveData<out Map<String, Any>> {
        return data
    }
}

В вашей деятельности:

private fun downloadInitInfo(){
    val downloadTaskClass = DownloadTaskClass()
    downloadTaskClass.execute("https://api.exchangeratesapi.io/latest?base=INR")
    downloadTaskClass.returnMapMethod().observe(this, Observer { 
        println(it) // "it" contains the `mutableMap` data
    })
}
Другие вопросы по тегам