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

Volatile变量在onResponse方法中未更新,Activity无法读取请求状态

解决Volley异步请求后状态无法同步到Activity的问题

刚接触Java和Android的话,遇到这种异步请求的状态同步问题太正常啦!咱们先搞清楚你原来的代码为什么不行,再给你一个简单易懂的解决方案。

问题根源:异步请求的时机问题

你在Activity里调用sendData.sendData()之后,马上就去判断sendData.isSend()——但Volley的网络请求是异步执行的,也就是说sendData()方法会立即返回,而实际的网络请求和响应处理是在后台线程完成的。这时候你判断isSend()的时候,请求还没完成,自然拿不到更新后的状态值。

哪怕你用了volatile修饰变量,也解决不了核心问题:变量还没被修改呢,可见性再好也没用~

解决方案:用回调接口处理异步结果

在Android里,处理异步操作最常用的方式就是回调接口——简单来说,就是让SendData类在请求完成的时候,主动通知Activity“我做完啦,结果是xxx”。

步骤1:定义回调接口

先写一个接口,用来规定请求成功和失败时的通知方法:

public interface OnRequestCompleteListener {
    // 请求成功时调用,传入解析后的数据
    void onSuccess(String parsedData);
    // 请求失败时调用
    void onFailure();
}

步骤2:修改SendData类,添加回调支持

给SendData类加一个回调成员变量,并且在请求完成时触发回调:

public class SendData {
    // 新增回调成员
    private OnRequestCompleteListener mListener;
    // 你的其他成员变量(queue、url、dataMap等)保持不变

    // 新增设置回调的方法
    public void setOnRequestCompleteListener(OnRequestCompleteListener listener) {
        this.mListener = listener;
    }

    public void sendData() {
        StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        String parsedData = parseHTML(response);
                        // 请求成功,通知Activity
                        if (mListener != null) {
                            mListener.onSuccess(parsedData);
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // 请求失败,通知Activity
                if (mListener != null) {
                    mListener.onFailure();
                }
            }
        }) {
            // 你的getParams方法保持不变
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                Iterator it = dataMap.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry pair = (Map.Entry) it.next();
                    params.put(pair.getKey().toString(), pair.getValue().toString());
                    it.remove();
                }
                return params;
            }
        };
        queue.add(stringRequest);
    }

    // 原来的setSend、setRetrievedData等方法如果不需要可以删掉,因为回调已经能传递状态和数据了
}

步骤3:在Activity中设置回调,处理结果

现在在Activity的posalji方法里,给SendData设置回调,在回调里处理请求成功或失败的逻辑:

private void posalji(String name, String jmb){
    SendData sendData = new SendData(getApplicationContext(), Constants.FIRSTtimeREQUEST_URL);
    HashMap<String, String> mapa = new HashMap<>();
    mapa.put("name", name);
    mapa.put("jmb", jmb);
    mapa.put("phone", pNumber);
    mapa.put("mac_address", getMacAddress());
    sendData.setDataMap(mapa);
    
    // 设置请求完成后的回调
    sendData.setOnRequestCompleteListener(new OnRequestCompleteListener() {
        @Override
        public void onSuccess(String parsedData) {
            // 这里是请求成功后的逻辑,比如更新UI、保存全局变量
            // 比如你原来写的"do something"就放在这里
            // 注意:Volley的响应回调是在主线程执行的,所以可以直接更新UI哦
        }

        @Override
        public void onFailure() {
            // 这里是请求失败后的逻辑
        }
    });
    
    // 发送请求
    sendData.sendData();
    // 这里不要再判断sendData.isSend()啦,因为请求还没完成
}

额外说明

  • 如果需要把返回的数据存入全局变量,直接在onSuccess方法里赋值就可以了,因为这个方法是在请求完成后才会执行的,能拿到最新的解析后的数据。
  • Volley的响应回调默认是在主线程执行的,所以你可以直接在onSuccess或onFailure里更新UI(比如修改TextView的文字、显示Toast等),不用额外切换线程,非常方便~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:32:10