因此,我正在尝试一个应用程序,并且正在发出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()同步,但又不阻塞主线程吗?
答案 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")
}
}