Котлин сопрограммы не загружают данные - PullRequest
0 голосов
/ 01 декабря 2018

Я использую корелины Kotlin в моем проекте Android.Я пытаюсь загрузить некоторые данные и отобразить их в текстовом виде.

Ниже приведен мой код

class MainActivity : AppCompatActivity() {

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

        tv.setOnClickListener {
            downloadData()
        }
    }


    private fun downloadData() {

        runBlocking {
            pb_activity_main.visibility = View.VISIBLE
            var data = ""
            async {
                data = downloadDataBlocking()
            }.await()
            tv.text = data
            pb_activity_main.visibility = View.GONE

        }
    }


    private fun downloadDataBlocking(): String {
        val client = OkHttpClient()
        val request = Request.Builder().url("https://jsonplaceholder.typicode.com/posts").build()
        val response = client.newCall(request).execute()
        return response.body()?.string() ?: ""
    }
}

Но данные не загружаются.Я не могу понять, почему.

Я включил интернет-разрешение в манифест, и URL-адрес также работает.

1 Ответ

0 голосов
/ 01 декабря 2018

Попробуйте это:

class MainActivity : AppCompatActivity(), CoroutineScope {

    private val job = Job()
    override val coroutineContext = Dispatchers.Main + job

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

        tv.setOnClickListener {
            downloadData()
        }
    }


    private fun downloadData() {
        launch {
            pb_activity_main.visibility = View.VISIBLE
            tv.text = withContext(Dispatchers.IO) { downloadDataBlocking() }
            pb_activity_main.visibility = View.GONE
        }
    }


    private fun downloadDataBlocking(): String {
        val client = OkHttpClient()
        val request = Request.Builder().url("https://jsonplaceholder.typicode.com/posts").build()
        val response = client.newCall(request).execute()
        return response.body()?.string() ?: ""
    }
}

Во-первых: никогда не следует использовать runBLocking 1006 * вне модульного тестирования или другого специального домена.

Эта функция не должна использоваться из сопрограммы.Он предназначен для связывания регулярного кода блокировки с библиотеками, написанными в стиле приостановки, для использования в основных функциях и в тестах.

Секунда:

Сопрограммы всегда связаны с некоторой локальной областью в вашем приложении , которая является сущностью с ограниченным временем жизни, , как элемент пользовательского интерфейса .

Вот почему Activity реализует CoroutineScope.Честно говоря, лучшее место для него - ViewModel или Presenter, но я не вижу ничего в коде ...

В-третьих, использовать async и await совершенно бессмысленносразу после его определения.Просто используйте withContext тогда.

...