如何从Retrofit的onResponse方法返回值并在其他方法中调用?
嘿,解决Retrofit异步请求数据拿不到的问题看这里!
首先得给你点明核心问题:Retrofit的网络请求是异步执行的——你调用请求方法后,代码会立刻往下走,不会傻等着请求完成,而onResponse是等请求成功拿到数据后,才会被系统“通知”执行。所以你在其他方法里直接访问getData列表时,大概率请求还没跑完,自然拿不到数据啦。
下面给你几种最简单的实现方式,挑你顺手的来:
方式一:用回调接口(纯基础操作,不用额外依赖)
这种方式最适合新手理解异步逻辑,纯Java/Kotlin就能搞定:
第一步:先定义个回调接口
public interface DataCallback { void onDataLoaded(List<YourDataModel> dataList); void onDataLoadFailed(String errorMsg); }
(把YourDataModel换成你自己的数据模型类哈)
第二步:修改你的请求方法,把回调传进去
比如你的getDataSeason改成这样:
private void getDataSeason(DataCallback callback) { // 这里是你的Retrofit初始化和请求代码,我给你补个示例 ApiService apiService = RetrofitClient.getClient().create(ApiService.class); Call<List<YourDataModel>> call = apiService.getSeasonData(); call.enqueue(new Callback<List<YourDataModel>>() { @Override public void onResponse(Call<List<YourDataModel>> call, Response<List<YourDataModel>> response) { if (response.isSuccessful() && response.body() != null) { // 把数据存到全局列表 listSeason = response.body(); // 告诉调用方:数据加载完啦! callback.onDataLoaded(listSeason); } else { callback.onDataLoadFailed("请求失败:" + response.message()); } } @Override public void onFailure(Call<List<YourDataModel>> call, Throwable t) { callback.onDataLoadFailed("网络出问题啦:" + t.getMessage()); } }); }
第三步:在需要用数据的地方,通过回调拿数据
比如在onCreate里:
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); listSeason = new ArrayList<>(); // 调用请求,传入回调逻辑 getDataSeason(new DataCallback() { @Override public void onDataLoaded(List<YourDataModel> dataList) { // 这里数据已经稳稳拿到了,放心调用其他方法处理 processData(dataList); } @Override public void onDataLoadFailed(String errorMsg) { // 弹个提示啥的处理错误 Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_SHORT).show(); } }); } // 你要调用的其他方法,在这里就能拿到完整数据了 private void processData(List<YourDataModel> dataList) { Log.d("我的数据", "拿到了" + dataList.size() + "条数据!"); // 剩下的逻辑随便写~ }
方式二:用LiveData(Android Jetpack推荐,更省心)
如果你的项目用了Android Jetpack,LiveData是更优雅的选择,它能自动跟着页面生命周期走,还不会内存泄漏:
第一步:定义个全局的LiveData对象
private MutableLiveData<List<YourDataModel>> seasonLiveData = new MutableLiveData<>();
第二步:修改请求方法,把数据传到LiveData里
private void getDataSeason() { ApiService apiService = RetrofitClient.getClient().create(ApiService.class); Call<List<YourDataModel>> call = apiService.getSeasonData(); call.enqueue(new Callback<List<YourDataModel>>() { @Override public void onResponse(Call<List<YourDataModel>> call, Response<List<YourDataModel>> response) { if (response.isSuccessful() && response.body() != null) { // 把数据post到LiveData,自动通知观察者 seasonLiveData.postValue(response.body()); } } @Override public void onFailure(Call<List<YourDataModel>> call, Throwable t) { // 可以传null或者错误信息,看你需求处理 seasonLiveData.postValue(null); } }); }
第三步:观察LiveData,数据更新时自动触发
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 观察LiveData,页面活着的时候才会收到通知 seasonLiveData.observe(this, new Observer<List<YourDataModel>>() { @Override public void onChanged(List<YourDataModel> dataList) { if (dataList != null) { // 数据更新了,直接调用方法处理 processData(dataList); } } }); // 发起请求 getDataSeason(); } private void processData(List<YourDataModel> dataList) { // 放心用数据就好啦 }
方式三:用Coroutines(Kotlin项目首选,代码像同步一样)
如果你用的是Kotlin,协程能把异步代码写得跟同步一样,超级清爽:
第一步:把请求改成挂起函数
private suspend fun getDataSeason(): List<YourDataModel>? { return try { val apiService = RetrofitClient.getClient().create(ApiService::class.java) apiService.getSeasonData() // 记得你的Retrofit接口要定义成suspend函数哦 } catch (e: Exception) { null } }
第二步:在生命周期里启动协程拿数据
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 用lifecycleScope,自动跟着页面生命周期销毁 lifecycleScope.launch { val dataList = getDataSeason() dataList?.let { // 拿到数据就调用方法 processData(it) } } } private fun processData(dataList: List<YourDataModel>) { // 随便造作数据啦 }
最后再提醒你一句!
绝对不要在调用getDataSeason()之后,马上就去访问listSeason——这时候请求肯定还没完成,列表铁定是空的。所有需要用数据的逻辑,都必须放在数据加载完成的回调里、LiveData的观察者里,或者协程挂起之后,这样才能保证拿到的是完整的数据~
内容的提问来源于stack exchange,提问作者Kharisma
相关产品推荐
相关产品推荐

