【问题标题】:Unable to get any string when calling a REST API调用 REST API 时无法获取任何字符串
【发布时间】:2019-07-22 16:35:29
【问题描述】:
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
import java.lang.Exception

...

private val client = OkHttpClient()

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

    val tvDisplay: TextView = findViewById(R.id.displayTV) as TextView
    tvDisplay.setOnClickListener {
        tvDisplay.text = run("https://jsonplaceholder.typicode.com/todos/1")
    }
}

@Throws(IOException::class)
fun run(url: String): String {
    val request = Request.Builder()
        .url(url)
        .build()
    try {
        client.newCall(request).execute().use { response -> return response.body().toString() }
    } 
    catch (e: Exception) {
        return e.message.toString()
    }
}

使用 android studio 和 kotlin。尝试调用 API 但我得到的只是 NULL 而不是它应该得到的字符串。

此外,如果 API 需要,我如何向此(用户名/密码)添加基本身份验证?

“@Throws”还有什么作用?

【问题讨论】:

    标签: android rest kotlin textview okhttp3


    【解决方案1】:

    通过代码进行更长的解释

    @Throws(IOException::class) // If IOException occur it will throw error to its parent the one that call to this function so you do not need try catch in this function
    fun run(url : String) : Response{
    
        val request = Request.Builder()
                .url(url)
                .get()
                .build()
    
        val client = OkHttpClient()
        return client.newCall(request).execute()
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        val tvDisplay: TextView = findViewById(R.id.displayTV) as TextView
        val thread = object : Thread() {    //Always use another thread from UIthread so UI will not lock while waiting get response from API
        override fun run() {
                try{
                    val _response = run("https://jsonplaceholder.typicode.com/todos/1").body()!!.string()
    
                    runOnUiThread { //Change to UI thread again if you need change somthing in UI
                        tvDisplay.setText(_response)
                    }
                }
                catch(e: Excpetion){
                    Log.d("Exception", e.toString())    //if anything error it goes here
                }
            }
        }
        thread.start()
    }
    

    【讨论】:

    • Log.d("Exception", e.toString()) 此日志存储在哪里?它会在文本文件的内部存储的android设备根目录上吗?所以如果我添加一个新线程,那么我需要改回UI线程,我怎么知道当前活动线程是什么?
    • 日志仅用于检查任何必要的调试程序,可以在 IDE 的日志部分查看。例如使用 Log 无需查看应用程序中的错误即可知道错误异常
    【解决方案2】:

    首先,我建议您研究 retrofit,因为我个人觉得它更容易使用(但如果您只进行一两次 REST 调用,可能会有点矫枉过正)

    我也可能会这样做

    client.newCall(request).enqueue(object: Callback {
        override fun onResult(call: Call, response: Response) {
            if (response.isSuccessful()) {
                return@run response.body.toString()
            }
        }
    )}
    

    异步。

    在 OkHttp imo 中添加身份验证很麻烦,最好从 here 回答,在 Retrofit 中更容易。

    最后,Throws 将函数标记为在从 Java 代码调用时有可能抛出 Exception(因为 Kotlin 和 Java 可以共存)

    【讨论】:

    • 谢谢。这是一个学习练习,我计划扩大规模,因此将进行改造。我在哪里可以找到这些库的 kotlin 示例?一切似乎都是Java。即使在使用自动代码转换器之后,我也必须使用大量的线索和错误来转换代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 2013-08-22
    • 2020-05-16
    相关资源
    最近更新 更多