有没有一种方法可以同步运行Okhttps请求?

时间:2020-08-26 13:24:35

标签: android kotlin okhttp

因此,我正在尝试一个应用程序,并且正在发出okhttp请求。我发现此请求任务是在其自己的线程上完成的,从而导致异步行为。

在下面,您会看到我的函数(该函数从API获取数据)和onCreateView函数(在此处我称为fetchData()。

@Throws(IOException::class)
    fun fetchData() {
        val client = OkHttpClient()
        val request: Request = Request.Builder()
            .url("https://www.themealdb.com/api/json/v1/1/search.php?f=a")
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                call.cancel()
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                val responseString = U.formatJson(response.body?.string())
                val meals = Gson().fromJson(responseString, Meals::class.java)
                
                Log.d(TAG, "First")
                
            }
        })
    }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        fetchData()

        Log.d(TAG, "second")

        return inflater.inflate(R.layout.fragment_home, container, false)
    }

所以我将这些日志放在这里,首先调用哪个Log,由于fetchData()是异步的,很明显,调用onCreateView()的Log.d(TAG,“ second”)被调用了第一。因此,如果我尝试使用下面正在请求的数据,由于请求尚未完成,因此我将返回null。那就是我的问题。调用函数后,我需要使用请求的数据。

有什么解决方案可以以某种方式使fetchData()同步,但又不阻塞主线程吗?

3 个答案:

答案 0 :(得分:1)

您不能在主线程上运行网络请求。 必须是异步的。只是猜测您在做什么,我会在您的提取函数中添加一个回调并像这样使用它。

fun fetchData(callback: (Meals?) -> Unit) {
    val client = OkHttpClient()
    val request: Request = Request.Builder()
        .url("https://www.themealdb.com/api/json/v1/1/search.php?f=a")
        .build()

    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            call.cancel()
            callback(null)
        }

        @Throws(IOException::class)
        override fun onResponse(call: Call, response: Response) {
            val responseString = U.formatJson(response.body?.string())
            val meals = Gson().fromJson(responseString, Meals::class.java)
            callback(meals)
        }
    })
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    fetchData { meals ->
        if (meals == null) 
            showErrorMessage()
        else
            updateSomeListAdapterWithMeals(meals)
    }

    return inflater.inflate(R.layout.fragment_home, container, false)
}

由于回调将在以后触发,因此在膨胀视图之前调用fetchData没关系。

答案 1 :(得分:0)

编辑:

感谢您的回答,由于没有其他有用的方法,我现在在回调函数中使用获取的数据。感谢您的回答

答案 2 :(得分:-1)

尝试以下代码进行同步请求:

@Throws(IOException::class)
    fun fetchData() {
        val client = OkHttpClient()
        val request: Request = Request.Builder()
            .url("https://www.themealdb.com/api/json/v1/1/search.php?f=a")
            .build()

       Response response = client.newCall(request).execute();

       if(response.isSuccessful()){
            val responseString = U.formatJson(response.body?.string())
            val meals = Gson().fromJson(responseString, Meals::class.java)
                
            Log.d(TAG, "First")             
        }else {
            Log.d(TAG, "Request failed")
        }
    }