如何在Kotlin重写的onSuccess函数中返回列表?
解决异步请求中返回数据的问题
你遇到的核心问题是网络请求是异步操作——clientInitialization函数发起请求后会立刻执行完毕,而onSuccess方法要等网络请求完成后才会被调用,所以没法直接从onSuccess里返回列表,必须用异步的方式传递结果。下面给你两种常用的解决方案:
方案一:自定义回调接口
这是处理异步回调的传统方式,通过定义一个接口来传递请求结果:
1. 定义回调接口
// 定义回调接口,用于传递成功/失败的结果 interface MovieInfoCallback { fun onSuccess(movieInfo: List<String>) fun onFailure(errorMessage: String) }
2. 修改原函数,加入回调参数
把movieInfoList的创建移到onSuccess里,请求完成后通过回调接口传递结果:
private fun clientInitialization( client: AsyncHttpClient, index: Int, movieAttributes: List<String>, callback: MovieInfoCallback ) { client["https://api.themoviedb.org/3/trending/movie/week?api_key=xxxxxx", object : JsonHttpResponseHandler() { override fun onSuccess(statusCode: Int, headers: Headers, json: JsonHttpResponseHandler.JSON) { val movieInfoList = mutableListOf<String>() val resultsArray = json.jsonObject.getJSONArray("results") val arrayLength = resultsArray.length() if (index < arrayLength) { // 提前获取指定索引的电影对象,避免重复调用getJSONArray val movieObject = resultsArray.getJSONObject(index) for (item in movieAttributes) { val currentAttribute = movieObject.getString(item) movieInfoList.add(currentAttribute) } } // 请求成功,通过回调返回结果 callback.onSuccess(movieInfoList) } override fun onFailure(statusCode: Int, headers: Headers?, errorResponse: String, throwable: Throwable?) { Log.d("Pic error", errorResponse) // 请求失败,传递错误信息 callback.onFailure(errorResponse) } }] }
3. 调用函数时处理结果
// 调用示例,传入回调处理结果 clientInitialization( client = yourAsyncHttpClientInstance, index = 0, movieAttributes = listOf("title", "release_date", "overview"), callback = object : MovieInfoCallback { override fun onSuccess(movieInfo: List<String>) { // 在这里拿到填充好的movieInfoList,做后续处理(比如更新UI) } override fun onFailure(errorMessage: String) { // 处理请求失败的情况 } } )
方案二:使用Kotlin协程(推荐)
Kotlin协程可以让你用同步的写法处理异步逻辑,代码更简洁易读,是现代Android开发的推荐方式:
1. 将函数改为挂起函数
用suspendCoroutine把异步回调包装成挂起函数,这样可以直接返回结果:
// 注意添加suspend关键字,把函数变成挂起函数 private suspend fun clientInitialization( client: AsyncHttpClient, index: Int, movieAttributes: List<String> ): List<String> = suspendCoroutine { continuation -> client["https://api.themoviedb.org/3/trending/movie/week?api_key=xxxxxx", object : JsonHttpResponseHandler() { override fun onSuccess(statusCode: Int, headers: Headers, json: JsonHttpResponseHandler.JSON) { val movieInfoList = mutableListOf<String>() val resultsArray = json.jsonObject.getJSONArray("results") val arrayLength = resultsArray.length() if (index < arrayLength) { val movieObject = resultsArray.getJSONObject(index) for (item in movieAttributes) { val currentAttribute = movieObject.getString(item) movieInfoList.add(currentAttribute) } } // 恢复协程,返回结果 continuation.resume(movieInfoList) } override fun onFailure(statusCode: Int, headers: Headers?, errorResponse: String, throwable: Throwable?) { Log.d("Pic error", errorResponse) // 恢复协程并抛出异常,方便上层捕获 val exception = throwable ?: Exception(errorResponse) continuation.resumeWithException(exception) } }] }
2. 在协程作用域中调用函数
协程必须在协程作用域内执行,比如在Activity/Fragment中可以用lifecycleScope,通用场景用CoroutineScope:
// 示例:在Activity中调用(需要依赖androidx.lifecycle:lifecycle-runtime-ktx) lifecycleScope.launch { try { val movieInfo = clientInitialization( client = yourAsyncHttpClientInstance, index = 0, movieAttributes = listOf("title", "release_date") ) // 在这里拿到结果,处理逻辑(比如更新UI) } catch (e: Exception) { // 捕获请求失败的异常,处理错误 } } // 通用场景调用 CoroutineScope(Dispatchers.IO).launch { try { val movieInfo = clientInitialization(...) // 如果需要更新UI,切换到主线程 withContext(Dispatchers.Main) { // 更新UI逻辑 } } catch (e: Exception) { // 处理错误 } }
额外优化建议
- 不要硬编码API Key,建议放到
strings.xml或者local.properties中,通过配置读取,避免泄露。 - 提取JSON解析逻辑到单独的函数,让代码更清晰。
- 注意空安全:比如调用
getString时,如果字段可能不存在,可以用optString避免崩溃。
内容的提问来源于stack exchange,提问作者Lyton_Spurz
相关产品推荐
相关产品推荐

