【问题标题】:Android Volley: How do I get the response from the server, whatever it might be?Android Volley:我如何从服务器获得响应,无论它可能是什么?
【发布时间】:2019-06-27 02:45:36
【问题描述】:

我开始使用 Kotlin 进行 Android 开发。我正在尝试使用 Volley 来读取 API 并更新 GUI 元素。我让它与使用 http GET 方法的StringObjectRequests 一起工作,现在我的问题是当我想使用 POST 方法时。

这是我的基本功能:

fun volley() {
    val queue = Volley.newRequestQueue(this)
    val url   = "http://x.x.x.x/api.php"
    val json = JSONObject()

    json.put("ciudad", "Londres")
    json.put("nombre", "Luis")

    val stringRequest = JsonObjectRequest(Request.Method.POST,
      url, json,
      Response.Listener<JSONObject> { response ->
        taContenido.setText(response.toString())
      },
      Response.ErrorListener {
        taContenido.setText("No Funcionó")
      })

    queue.add(stringRequest)
  }

“API”中的代码很简单……

<?php
$j = array('ciudad' => $_POST["ciudad"],
   'nombre' => $_POST["nombre"]);

echo json_encode($j);

我的问题是,当我运行该函数时,它会通过ErrorListener 部分并显示“No Funcionó”。我不知道为什么。当然,如果我使用 Postman 尝试我的 API,它会返回预期的 {"ciudad":"Londres","nombre":"Luis"}

那么,在使用JsonObjectRequest 时,我如何查看服务器返回的内容,无论它是什么?

如果我将 Request 更改为 StringRequest,我当然可以看到 PHP 错误(因为不会定义 $_POST[] :|

【问题讨论】:

  • 对不起,我不明白。我从哪里获得 networkResponse? var nr : NetworkResponse = error.networkResponse ???它抱怨未解决对 networkResponse 的引用
  • Response.ErrorListener 内尝试使用it.networkResponse
  • 或者做这样的事情Response.ErrorListener { error -&gt;
  • it.networkResponse 是我尝试的第一件事,它返回一个Attempt to read from field 'byte[] com.android.volley.NetworkResponse.data' on a null object reference
  • 如果我强制 API tu 手动返回一个 json 对象,一切正常,所以看起来 API 永远不会收到 POST,但我不能确定我是否看不到什么它来自服务器

标签: android kotlin android-volley


【解决方案1】:

我在 Java 中发帖。请在 Kotlin 中转换。像这样创建一个单例类 -

public class VolleyManager {
    private static VolleyManager ourInstance;
    private final Context mContext;
    private final ImageLoader mImageLoader;
    private RequestQueue mRequestQueue;

    private VolleyManager(final Context pContext) {
        mContext = pContext;
        mImageLoader = new ImageLoader(getRequestQueue(), new ImageLoader.ImageCache() {
            private LruCache<String, Bitmap> mCache = new LruCache<>(20);

            @Override
            public Bitmap getBitmap(final String url) {
                return mCache.get(url);
            }

            @Override
            public void putBitmap(final String url, final Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
        });
    }

    private RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(mContext);
        }
        return mRequestQueue;
    }

    public static synchronized VolleyManager getInstance(final Context pContext) {
        if (ourInstance == null) {
            ourInstance = new VolleyManager(pContext);
        }
        return ourInstance;
    }

    public void addRequest(final Request pRequest) {
        getRequestQueue().add(pRequest);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(tag);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

并提出这样的要求 -

public class AccessTokenRequest extends StringRequest {
    Map<String,String> mParms = new ArrayMap<>();
    Map<String,String> mHeader = new ArrayMap<>();

    public AccessTokenRequest(String code, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        super(Method.POST, WebConfig.END_POINT + WebConfig.ACCESS_TOKEN_METHOD, listener, errorListener);
        mHeader.put("Authorization","Basic MjJEUT");
        mHeader.put("Content-Type","application/x-www-form-urlencoded");
        mParms.put("clientId","63FGDF");
        mParms.put("grant_type","authorization_code");
        mParms.put("redirect_uri","https://example.com/thu");
        mParms.put("code",code);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return mHeader;
    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return mParms;
    }
}

在活动中,像这样调用 -

private void requestAccessToken(String code) {

        final ProgressDialog pDialog = new ProgressDialog(this);
        pDialog.setMessage("Loading...");
        pDialog.setCancelable(false);
        pDialog.setCanceledOnTouchOutside(false);
        pDialog.show();

        VolleyManager.getInstance(AuthorizationActivity.this).addRequest(new AccessTokenRequest(code, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONObject responseJsonObj = new JSONObject(response);
                    String accessToken = responseJsonObj.getString("access_token");
                    long expiresIn = responseJsonObj.getInt("expires_in") + (System.currentTimeMillis() / 1000);
                    String refreshToken = responseJsonObj.getString("refresh_token");
                    List<Scope> scopes = parseScopes(responseJsonObj.getString("scope"));
                    String tokenType = responseJsonObj.getString("token_type");
                    String userId = responseJsonObj.getString("user_id");



                } catch (JSONException e) {
                    e.printStackTrace();
                } finally {
                    pDialog.dismiss();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                pDialog.dismiss();
                Toast.makeText(AuthorizationActivity.this, "Please check internet connection", Toast.LENGTH_LONG).show();
            }
        }));
    }

【讨论】:

  • 这是一个完整的java代码。我认为这个答案不值得投反对票。如果有人不能理解这个简单的代码,那么请至少不要投反对票。谢谢。
猜你喜欢
  • 2020-07-17
  • 2019-08-20
  • 1970-01-01
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-12
相关资源
最近更新 更多