Volley Request 将之前的值设置为 TextView

Volley Request Sets the previous value to TextView

我想了解 volley 在 android 中是如何使用的,所以在我的项目中,我正在查询 http://uinames.com/api/?amount=1

中的单个名称

在应用程序中,我有一个按钮调用函数来发出请求,然后将其设置到 TextView。同样出于调试目的,我记录了来自 url 的响应。单击按钮时,logcat 中可以正确看到响应,但直到下次单击按钮时,文本才会设置到 TextView。

这是 JsonObjectRequest 的代码

public String getName() {
        JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.GET,
                URL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            full_name = response.getString(name) + " " + response.getString(last);
                            Log.d(TAG, full_name);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                });
        AppController.getInstance().addToRequestQueue(objectRequest, "");

        return full_name;
    } 

以下是调用 getName() 方法的 MainActivity 中的代码

mButton = (Button) findViewById(R.id.btn);
        mTextView = (TextView) findViewById(R.id.text);

        final RequestClass newReq = new RequestClass();

        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                name = newReq.getName();
                mTextView.setText(name);
            }
        });

Volley 库已弃用,因此请勿使用 Volley 库。

Volley 的最佳替代品是 RetroFit 库。

这样试试

public void getName() {
        JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.GET,
                URL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            full_name = response.getString("name") + " " + response.getString("last");

                            runOnUiThread(new Runnable() {
    @Override
    public void run() {
       //Your code to run in GUI thread here
        mTextView.setText(full_name);
    }
    });
                            Log.d(TAG, full_name);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                });
        AppController.getInstance().addToRequestQueue(objectRequest, "");


    } 




mButton = (Button) findViewById(R.id.btn);
        mTextView = (TextView) findViewById(R.id.text);



        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getName();

            }
        });

调用函数 String getName() 时会发生以下情况:

  1. 构造了一个JsonObjectRequest,并将响应和错误侦听器传递给请求。请注意,监听器只有在相应事件发生后才会执行。
  2. JsonObjectRequest被添加到请求队列中,当线程池中的线程可用时执行。
  3. 直到现在 full_name 变量还没有被触及,你 return 分配给它的最后一个值(这就是为什么当你再次点击按钮时,你会在你的文本视图)。
  4. 您的请求得到响应,并且在您的函数 returned 之后调用侦听器为 full_name 分配新值。这是您在下次调用 getName() 时获得的值。 . .

一般来说,像getName这样的函数不能立即执行网络操作,return其结果。它要么需要 阻塞 直到它收到来自服务器的响应(这是 android 中的 prohibited)。或者,它可以 return 尚未获取结果,并有一个回调函数(或监听器),当结果可用时调用该回调函数(这是 Volley 库中的通用方法)。

这意味着您必须在响应监听器中 setText。我注意到您的网络请求 RequestClass 有一个单独的 class,为了保持您的设计不变,一种解决方案是将侦听器传递给 getName() 函数(以及所有其他在此 class 中执行网络操作的函数),它可能看起来像这样:

public void getName(Response.Listener<JSONObject> responseListener,
                    Response.ErrorListener errorListener) {
    JsonObjectRequest objectRequest = new JsonObjectRequest(Request.Method.GET,
            URL, null, responseListener, errorListener);
    AppController.getInstance().addToRequestQueue(objectRequest, "");
}

并且在你的 activity 中,你必须像这样传递听众:

mButton.setOnClickListener(new View.OnClickListener() {
    @Override 
    public void onClick(View view) {
        name = newReq.getName(
                new Response.Listener<JSONObject>() {
                    @Override 
                    public void onResponse(JSONObject response) {
                        try {
                            String full_name = response.getString("name") + " " + response.getString("last");
                            mTextView.setText(full_name);
                            Log.d(TAG, full_name);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, 
                new Response.ErrorListener() {
                    @Override 
                    public void onErrorResponse(VolleyError error) {
                    }
                });
    }

});

作为更好的设计,您可能希望避免从 activity 传递 Volley 侦听器(它不必知道任何有关 volley 的信息),因此您可能希望定义您自己的侦听器接口,覆盖并将其从 activity 传递到您的网络 class(在其中实例化您的 Response.ListenerResponse.ErrorListener 并覆盖它们以在您的侦听器中调用函数).