You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Retrofit2 enqueue的onResponse晚于return执行问题求助

问题根源分析

你遇到的是典型的异步请求执行顺序问题:Retrofit的enqueue()是异步发起网络请求的,它会把请求放到后台线程处理,主线程不会等待请求完成,会直接执行后续的return listTokens代码。这时候onResponse还没被调用,listTokens自然是空的。Thread.sleep()没用是因为它只会阻塞主线程,既没法让异步请求提前完成,还可能引发ANR(应用无响应)。


解决方案

方案1:自定义回调接口(最直接的改造方式)

不让getTokens()直接返回列表,而是定义回调接口,在onResponse中通过回调传递数据。

  1. 定义回调接口
public interface TokenCallback {
    void onSuccess(ArrayList<Tokens> tokensList);
    void onFailure(String errorMessage);
}
  1. 修改HelperTokens的getTokens()方法
public void getTokens(TokenCallback callback) {
    ArrayList<Tokens> listTokens = new ArrayList<>();
    Retrofit myRetro = APIService.getInstancia();
    TokensService myTokensService = myRetro.create(TokensService.class);

    myTokensService.getAllTokens().enqueue(new Callback<Object>() {
        @Override
        public void onResponse(Call<Object> call, Response<Object> response) {
            if (response.isSuccessful() && response.body() != null) {
                Map<String, Map> datos = (Map<String, Map>) response.body();
                for (Map.Entry<String, Map> item : datos.entrySet()){
                    Tokens eachToken = new Tokens();
                    eachToken.setTheToken((String) item.getValue().get("theToken"));
                    eachToken.setfCreacion((String) item.getValue().get("fCreacion"));
                    eachToken.setLimited((double) item.getValue().get("isLimited"));
                    eachToken.setfVencimiento((String) item.getValue().get("fVencimiento"));
                    listTokens.add(eachToken);
                }
                // 请求成功,通过回调返回数据
                callback.onSuccess(listTokens);
            } else {
                callback.onFailure("请求失败,响应为空");
            }
        }

        @Override
        public void onFailure(Call<Object> call, Throwable t) {
            callback.onFailure(t.getMessage());
        }
    });
}
  1. 调用方式
helperTokens.getTokens(new TokenCallback() {
    @Override
    public void onSuccess(ArrayList<Tokens> tokensList) {
        // 在这里处理拿到的Token列表,比如更新UI
        Log.d("拿到的Token列表", tokensList.toString());
    }

    @Override
    public void onFailure(String errorMessage) {
        // 处理错误情况
        Log.d("请求失败", errorMessage);
    }
});

方案2:使用Kotlin协程(推荐,代码更简洁)

如果项目支持Kotlin,协程可以让异步代码看起来像同步逻辑,避免回调嵌套。

  1. 修改TokensService为挂起函数
interface TokensService {
    @GET("Tokens.json")
    suspend fun getAllTokens(): Response<Map<String, Map<String, Any>>>

    @POST("Tokens.json")
    suspend fun postToken(@Body miToken: Tokens): Response<Any>
}
  1. 改写getTokens()为挂起函数
suspend fun getTokens(): ArrayList<Tokens> {
    val listTokens = ArrayList<Tokens>()
    val myRetro = APIService.getInstancia()
    val myTokensService = myRetro.create(TokensService::class.java)

    try {
        val response = myTokensService.getAllTokens()
        if (response.isSuccessful && response.body() != null) {
            val datos = response.body()!!
            for ((_, value) in datos) {
                val eachToken = Tokens().apply {
                    theToken = value["theToken"] as String
                    fCreacion = value["fCreacion"] as String
                    limited = value["isLimited"] as Double
                    fVencimiento = value["fVencimiento"] as String
                }
                listTokens.add(eachToken)
            }
        }
    } catch (e: Exception) {
        Log.d("Fallo", e.message.toString())
    }
    return listTokens
}
  1. 调用方式(在协程作用域中执行)
lifecycleScope.launch { // Activity/Fragment中用lifecycleScope,ViewModel中用viewModelScope
    val tokensList = helperTokens.getTokens()
    // 处理拿到的Token列表
    Log.d("拿到的Token列表", tokensList.toString())
}

方案3:使用LiveData(适合MVVM架构)

如果项目采用MVVM,用LiveData可以自动观察数据变化,更新UI。

  1. 修改HelperTokens的getTokens()方法
public LiveData<ArrayList<Tokens>> getTokens() {
    MutableLiveData<ArrayList<Tokens>> tokensLiveData = new MutableLiveData<>();
    ArrayList<Tokens> listTokens = new ArrayList<>();
    Retrofit myRetro = APIService.getInstancia();
    TokensService myTokensService = myRetro.create(TokensService.class);

    myTokensService.getAllTokens().enqueue(new Callback<Object>() {
        @Override
        public void onResponse(Call<Object> call, Response<Object> response) {
            if (response.isSuccessful() && response.body() != null) {
                Map<String, Map> datos = (Map<String, Map>) response.body();
                for (Map.Entry<String, Map> item : datos.entrySet()){
                    Tokens eachToken = new Tokens();
                    eachToken.setTheToken((String) item.getValue().get("theToken"));
                    eachToken.setfCreacion((String) item.getValue().get("fCreacion"));
                    eachToken.setLimited((double) item.getValue().get("isLimited"));
                    eachToken.setfVencimiento((String) item.getValue().get("fVencimiento"));
                    listTokens.add(eachToken);
                }
                tokensLiveData.setValue(listTokens);
            } else {
                tokensLiveData.setValue(null);
            }
        }

        @Override
        public void onFailure(Call<Object> call, Throwable t) {
            tokensLiveData.setValue(null);
            Log.d("Fallo", t.getMessage());
        }
    });

    return tokensLiveData;
}
  1. 调用方式(观察LiveData)
helperTokens.getTokens().observe(this, new Observer<ArrayList<Tokens>>() {
    @Override
    public void onChanged(ArrayList<Tokens> tokens) {
        if (tokens != null) {
            // 处理拿到的Token列表
            Log.d("拿到的Token列表", tokens.toString());
        } else {
            // 处理错误情况
        }
    }
});

内容的提问来源于stack exchange,提问作者DFDev3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:57:52