有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaAndroid:Volley HTTP补丁请求

我刚开始从我现有的网络库移植到Android的Volley。到目前为止,我已经成功地实现了适用的截击ImageLoader。现在,我正在尝试启动并运行我的第一个http调用,但发现了这个错误

注意:我故意从一个补丁请求开始,因为我会经常使用它们。此外,我的Volley版本也支持补丁: https://安卓.googlesource.com/platform/frameworks/volley/+/master/src/com/安卓/volley/Request.java https://安卓.googlesource.com/platform/frameworks/volley/+/master/src/com/安卓/volley/toolbox/HurlStack.java

堆栈跟踪:

E/InputDialogFragment(27940): VolleyError: java.net.ProtocolException: Connection already established
D/Volley  (27940): [1] MarkerLog.finish: (67   ms) [ ] https://mobile.example.com/m/api/v1/user/ 0xb33a3c8d NORMAL 2
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [ 1] add-to-queue
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [544] cache-queue-take
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [544] cache-miss
D/Volley  (27940): [1] MarkerLog.finish: (+0   ) [545] network-queue-take
D/Volley  (27940): [1] MarkerLog.finish: (+14  ) [545] post-error
D/Volley  (27940): [1] MarkerLog.finish: (+53  ) [ 1] done

补丁请求

    HashMap<String, Object> values = new HashMap<String, Object>();
    values.put(mParam, val);
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.PATCH, APIConstants.URL_USER, new JSONObject(values),
        new Response.Listener<JSONObject>(){
            @Override
            public void onResponse(JSONObject response){
               // Blah do stuff here 
                mProgressDialog.dismiss();
            }
        },
        new Response.ErrorListener(){
            @Override
            public void onErrorResponse(VolleyError error){
                Log.e(TAG, "VolleyError: " + error.getMessage());
            }
        }){
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                VolleySingleton.getInstance().addCookie(headers);
                return headers;
            }
    };
    VolleySingleton.getInstance().getRequestQueue().add(request);

是的,我计划最终为StringRequest、JsonObjectRequest等构建类。。。但目前我只想启动一个

此外,如果你想了解addCookie,现在我更喜欢将我的cookie保存在preferences中,因为我对CookieManager不太熟悉

单打

public class VolleySingleton {
    private static final String COOKIE_KEY = "Cookie";
    private static VolleySingleton mInstance = null;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private SharedPreferences mPreferences;
    private VolleySingleton(){
        mRequestQueue = Volley.newRequestQueue(MyApplication.getAppContext());
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
        mPreferences = MyApplication.getAppContext().getSharedPreferences(PrefConstants.PREFERENCES, 0);
    }

    public static VolleySingleton getInstance(){
        if(mInstance == null){
            mInstance = new VolleySingleton();
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        return this.mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return this.mImageLoader;
    }

    public final void addCookie(Map<String, String> headers) {
        String cookie = mPreferences.getString(PrefConstants.PREF_COOKIE, null);
        if(cookie != null){
            headers.put(COOKIE_KEY, cookie);
        }
    }
}

共 (3) 个答案

  1. # 1 楼答案

    我也有这个问题,我的解决方案是放弃底层内置的Apache HTTP组件,使用Square中的OkHttp库,使用this ^{} implementation进行截击,使用OkHttp作为其传输。效果很好

  2. # 2 楼答案

    我知道这个问题由来已久,但提供解决方案可以帮助尚未遇到同样挑战的人

    JSONObject param = new JSONObject();
        try {
            param.put(KEY 1, VALUE 1);
            param.put(KEY 2, VALUE 2);
    
        } catch (JSONException e) {
            e.printStackTrace();
        }
    
            //ID represents the id for the record to update
        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.PATCH, YOUR URL+ "?ID=" + ID, param,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                     //call handler to display response (optional)
    
                    }
                }, new Response.ErrorListener() {
    
            @Override
            public void onErrorResponse(VolleyError error) {
                //call handler to display response (optional)
    
            }
    
        }) {
    
            //            Passing header
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Content-Type", "application/json; charset=utf-8");
                headers.put("x-api-key", "YOUR API KEY");
                return headers;
            }
    
            @Override
            protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
    
               //use this to check positive response code returned else remove this override part
    
                return super.parseNetworkResponse(response);
            }
        };
        //and then you pass json data to volley
        VolleySingleton.getInstance(getActivity()).addToRequestQueue(jsonObjReq);
    
  3. # 3 楼答案

    问题:

    Volleys HurlStack(HttpUrlConnection)确实有补丁的支持代码。然而,每当您试图发出补丁请求时,它似乎仍会抛出“我的标题”和“堆栈跟踪”中发布的异常

    黑客解决方案:

    1)强制截击使用HttpClientStack

    下面是我的截击单例构造函数的更新版本。这“有效”,但显然浪费了Hurl实现,如果(Build.VERSION.SDK_INT>;=9),则认为Hurl实现更好。更不用说谷歌计划在未来完全放弃apache HttpClient

    private VolleySingleton(){
        mPreferences = MyApplication.getAppContext().getSharedPreferences(PrefConstants.PREFERENCES, 0);
    
        String userAgent = "volley/0";
        try {
            String packageName = MyApplication.getAppContext().getPackageName();
            PackageInfo info = MyApplication.getAppContext().getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException e) {}
    
        HttpStack httpStack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
        mRequestQueue = Volley.newRequestQueue(MyApplication.getAppContext(), httpStack);
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> mCache = new LruCache<String, Bitmap>(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
    }
    

    2)继续使用上述截击动作,仅限于打补丁;将其重命名为VolleySingletonPatch(),然后为所有其他非补丁调用创建默认的VolleySingleton()。(优于1,但仍不是最优)

    3)解决HurlStack中抛出的异常,尽管Volley已经实现了补丁。这将是最好的,但我宁愿避免直接修补凌空或不必要地扩展自己的httpstack

    我没有回答这个问题,因为我非常感谢任何见解,当然还有比我在这里提出的更好的选择