just started learning Kotlin. I'm trying to use okhttp to send a simple get request to a URL that contains only text.
I want the output of the request stored in a liveData variable, but when I run it, it crashes. Here's the class:
// gradle dependency added to build.gradle:
// implementation("com.squareup.okhttp3:okhttp:4.5.0")
//
// added this permission to AndroidManifest.xml just above the "application" section
// <uses-permission android:name="android.permission.INTERNET" />
//
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException
class GetExample {
private val client = OkHttpClient()
private val _theResult = MutableLiveData<String?>()
val theResult: LiveData<String?> = _theResult
@Throws(IOException::class)
fun getText(url: String) {
val request = Request.Builder().url(url).build()
try {
client.newCall(request).execute()
.use { response -> _theResult.value = response.body?.string() }
} catch (e: IOException) {
_theResult.value = e.message
}
}
}
And to call this I'm using
val url = "https://raw.github.com/square/okhttp/master/README.md"
GetExample().getText(url)
and accessing the result with
var thisString: String? = GetExample().theResult.value
Help greatly appreciated
CodePudding user response:
Lets break down a little what your code does, shall we?
val url = "https://raw.github.com/square/okhttp/master/README.md"
GetExample().getText(url)
var thisString: String? = GetExample().theResult.value
You first assign the url variable to be a github link. Then, you construct a new GetExample object and call getText on it, with the url parameter. But now, you are assigning thisString to a new instance of GetExample, which means it doesn't contain the data from the object you called getText on.
To fix this problem, one might write something like this:
val url = "https://raw.github.com/square/okhttp/master/README.md"
val getter = GetExample()
getter.getText(url)
var thisString: String? = getter.theResult.value
What george said is true as well, but I haven't tested that so you need to take a look if that is a problem as well.
CodePudding user response:
You are trying to execute this on the UI thread. That will not work.
Just try to run it on another thread, like the IO Thread,
and use postValue
in liveData
. Otherwise, you need to set the value on the UI thread.
E.g.,
try {
runBlocking(IO) {
client.newCall(request).execute()
.use { response -> _theResult.postValue(response.body?.string()) }
}
} catch (e: IOException) {
_theResult.value = e.message
}