Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9380

How to acces view properties from coroutines result

I am trying to do simple request to backend with coroutines

    uiScope.launch {
        try {
             result = URL("https://httpbin.org/get").readText()
            text.text = result
        } catch (error: Error) {
            text.text = error.message
        } finally {
                log(this@MainActivity,result)

        }
    }

but this exeption is thrown:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

How to solve it?

Upvotes: 1

Views: 1104

Answers (2)

Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9380

I found solution. I can not access UI component from another thread, at the same time I can not make internet request on the main thread. So I should chouse one of them. Solution was to use ViewModel components and update it's LiveDate value which subsequently will chane the UI

    var viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
    viewModel.selected.observe(this, Observer{ users ->

        text.text = users
    })
    uiScope.launch {
            try {
                result = URL("http://jsonplaceholder.typicode.com/posts").readText()
                viewModel.selected.postValue(result)
            } catch (error: Error) {
                viewModel.selected.postValue(error.toString())
            }

    }
    log(this@MainActivity,result)

Upvotes: 2

Marko Topolnik
Marko Topolnik

Reputation: 200148

Your uiScope isn't set up correctly, apparently its dispatcher is not Dispatchers.Main. So the first thing to fix is your implementation of the coroutineContext property, which should be

override val coroutineContext = Dispatchers.Main + SupervisorJob()

Once you fix that, your code will be making a blocking call on the UI thread. To make the blocking call on a background thread, but still keep the rest of the coroutine on the UI thread, write

uiScope.launch {
    try {
         text.text = withContext(Dispatchers.IO) {
             URL("https://httpbin.org/get").readText()
         }
    } catch (e: Exception) {
        text.text = e.message
    } finally {
        log(this@MainActivity, result)
    }
}

Upvotes: 0

Related Questions