Android开发中Volley异步请求返回ArrayList为空问题排查
问题根因
Volley发起的网络请求是异步非阻塞的:当你调用add(jsonObjectRequest)把请求加入队列后,当前线程不会暂停等待网络请求完成、onResponse回调执行,而是会立刻继续往下执行return u1语句。
此时网络请求还在后台排队/传输,onResponse根本没有触发,你定义的静态集合u1里还没有被添加任何数据,所以调用方法后立刻读取集合size,得到的结果必然是0。
另外你当前代码还有两个隐藏问题:
- 用静态全局集合
u1存储单次请求结果,多次调用方法会导致历史数据残留,出现列表重复、数据错乱 - 方法内新建了
RequestQueue实例但没有使用,实际往MainActivity的静态队列加请求,容易出现队列空指针、重复创建队列浪费资源的问题
改造方案
异步网络请求的结果永远无法通过方法return直接返回,必须通过回调接口在请求完成时把结果传递出去,具体改造步骤如下:
- 定义请求结果回调接口,用来接收成功/失败的回调通知
public interface UserLoadCallback { void onSuccess(ArrayList<User> userList); void onLoadFailed(Exception error); }
- 重构
getUserPicture方法,移除全局静态集合,增加回调参数,在请求成功/失败时触发对应回调
public class Utils { public static void getUserPicture(String uid, Activity activity, UserLoadCallback callback) { // 初始化全局请求队列,避免重复创建 if (MainActivity.requestQueue == null) { MainActivity.requestQueue = Volley.newRequestQueue(activity.getApplicationContext()); } JSONObject requestParams = new JSONObject(); String requestUrl = "https://ewserver.helpme/helpme.php"; try { requestParams.put("uid", uid); } catch (JSONException e) { callback.onLoadFailed(e); return; } JsonObjectRequest profileRequest = new JsonObjectRequest( Request.Method.POST, requestUrl, requestParams, response -> { ArrayList<User> resultList = new ArrayList<>(); try { String pictureUrl = response.getString("picture"); resultList.add(new User(uid, pictureUrl)); callback.onSuccess(resultList); } catch (JSONException e) { callback.onLoadFailed(e); } }, error -> callback.onLoadFailed(error) ); MainActivity.requestQueue.add(profileRequest); } }
- 修改调用逻辑,在回调方法中处理拿到的用户列表数据,不要在方法调用后立刻读取结果
getUserPicture(uid, activity, new UserLoadCallback() { @Override public void onSuccess(ArrayList<User> userList) { // 此处网络请求已完成,数据解析成功,可以正常使用列表 Log.d("main_activity_usersize", String.valueOf(userList.size())); // 如需更新UI,注意要在主线程执行 } @Override public void onLoadFailed(Exception error) { // 在此处处理网络错误、解析错误逻辑 error.printStackTrace(); } });
注意事项
- Android禁止在主线程执行同步网络请求,否则会触发ANR崩溃,不要尝试用阻塞线程的方式等待异步请求返回
- 单次请求的结果存在方法局部变量中即可,不要用静态全局集合存储,避免多请求数据污染
- Volley的
RequestQueue建议做成应用级单例,不要每次请求都新建实例,减少内存开销
内容的提问来源于stack exchange,提问作者Elly
相关产品推荐
相关产品推荐

