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

Retrofit2中全局List变量赋值后返回null的技术咨询

问题分析与解决方案:异步请求导致返回null

兄弟,你这个问题我太熟了——这完全是异步请求的执行顺序坑到你了!咱们来拆解一下代码的执行流程,你就明白为啥返回null了:

  1. 你调用retrieveDogsFromREST()方法后,代码会立刻发起异步网络请求(enqueue()方法就是把请求放到后台线程去跑)
  2. 主线程可不会等后台的网络请求完成,它会直接跳过onResponse回调,执行后面的Log.d("onRetrieveDR", ""+ responseDogs),这时候responseDogs还没被赋值,可不就是null吗?
  3. 等网络请求成功返回后,onResponse才会被调用,这时候responseDogs才被赋值,但这时候retrieveDogsFromREST()早就已经把null返回给调用方了!

说白了就是:你想在同步方法里直接拿异步请求的结果,这根本行不通——异步操作的结果不会立刻就绪。

下面给你几种常用的解决方案,你可以根据项目情况选:

方案1:用自定义回调接口(最基础的原生方案)

咱们不用方法返回值,而是定义一个回调接口,等请求成功后再把结果传回来:

首先定义回调接口:

public interface DogRetrievalCallback {
    void onSuccess(List<Dog> dogs);
    void onFailure(int errorCode);
}

然后修改你的retrieveDogsFromREST方法,把回调传进去:

public void retrieveDogsFromREST(DogRetrievalCallback callback) {
    final DogService dogService = DogService.serviceDog;
    dogService.getDogs(AuthRequest.createAuthJsonString()).enqueue(new Callback<DogList>() {
        @Override
        public void onResponse(Call<DogList> call, Response<DogList> response) {
            if (response.isSuccessful()) {
                List<Dog> dogs = response.body().getDogs();
                Log.d("DogRESTSuccessful", "" + dogs);
                callback.onSuccess(dogs); // 请求成了,把结果给回调
            } else {
                Log.d("DogRESTNSuccessful", "- statusCode" + response.code());
                callback.onFailure(response.code()); // 失败了传错误码
            }
        }

        @Override
        public void onFailure(Call<DogList> call, Throwable t) {
            callback.onFailure(-1); // 网络异常传个自定义错误码
            t.printStackTrace();
        }
    });
}

调用的时候这么用:

dogREST.retrieveDogsFromREST(new DogRetrievalCallback() {
    @Override
    public void onSuccess(List<Dog> dogs) {
        // 这里就能拿到非空的dogs列表了,想干嘛干嘛(比如更新UI)
    }

    @Override
    public void onFailure(int errorCode) {
        // 处理错误情况,比如弹个Toast提示用户
    }
});

方案2:用LiveData(适合Android Jetpack项目)

如果你的项目用了Android架构组件,用LiveData来观察数据变化会更优雅,还能自动处理生命周期:

先把responseDogs改成LiveData类型:

private MutableLiveData<List<Dog>> responseDogs = new MutableLiveData<>();

public LiveData<List<Dog>> retrieveDogsFromREST() {
    final DogService dogService = DogService.serviceDog;
    dogService.getDogs(AuthRequest.createAuthJsonString()).enqueue(new Callback<DogList>() {
        @Override
        public void onResponse(Call<DogList> call, Response<DogList> response) {
            if (response.isSuccessful()) {
                List<Dog> dogs = response.body().getDogs();
                Log.d("DogRESTSuccessful", "" + dogs);
                responseDogs.postValue(dogs); // 后台线程更新LiveData要用postValue
            } else {
                Log.d("DogRESTNSuccessful", "- statusCode" + response.code());
                responseDogs.postValue(null);
            }
        }

        @Override
        public void onFailure(Call<DogList> call, Throwable t) {
            responseDogs.postValue(null);
            t.printStackTrace();
        }
    });
    return responseDogs;
}

然后在Activity/Fragment里观察这个LiveData:

dogREST.retrieveDogsFromREST().observe(this, new Observer<List<Dog>>() {
    @Override
    public void onChanged(List<Dog> dogs) {
        if (dogs != null) {
            // 拿到数据,处理业务逻辑
        } else {
            // 处理错误
        }
    }
});

方案3:用Coroutines(Kotlin/Java都支持,代码更简洁)

如果项目用了协程(Java可以用kotlinx-coroutines-java库),可以把异步请求写成同步风格的代码,不用写回调:

Kotlin示例(挂起函数):

suspend fun retrieveDogsFromREST(): List<Dog>? {
    return try {
        val dogService = DogService.serviceDog
        val response = dogService.getDogs(AuthRequest.createAuthJsonString()).await()
        if (response.isSuccessful) {
            response.body()?.dogs
        } else {
            Log.d("DogRESTNSuccessful", "- statusCode" + response.code())
            null
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

调用的时候要在协程作用域里:

lifecycleScope.launch {
    val dogs = dogREST.retrieveDogsFromREST()
    if (dogs != null) {
        // 处理数据
    }
}

Java的话可以用runBlocking或者CoroutineScope的Java API,不过Kotlin协程的写法会更清爽。

总之核心就是:异步操作的结果不能在发起请求后立刻获取,必须用回调、LiveData、协程这类异步处理方式来接收结果,不能像同步代码那样直接返回变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:28:29