java - Android: Volley HTTP 补丁请求

标签 java android http httpurlconnection android-volley

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

注意:我特意从 PATCH 请求开始,因为我会经常使用它们。另外,我的 Volley 版本支持补丁: https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/Request.java https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/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 保存在首选项中,因为我对 CookieManager 不太熟悉。

Volley 单例

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);
        }
    }
}

最佳答案

问题:

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

黑客解决方案:

1) 强制 Volley 使用 HttpClientStack。

下面是我的 VolleySingleton 构造函数的更新版本。这“有效”,但显然浪费了 Hurl 实现,如果 (Build.VERSION.SDK_INT >= 9) 被认为更好。更不用说 Google 计划在未来完全放弃 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) 继续使用上面的 VolleySingleton ONLY 打补丁;将其重命名为 VolleySingletonPatch(),然后当然会为所有其他非 PATCH 调用创建默认的 VolleySingleton()。 (优于 1,但仍然不是最优的)

3) 解决HurlStack抛出的异常,尽管Volley已经实现了PATCH。这将是最好的,但我更愿意避免直接修改 Volley 或不必要地扩展我自己的 HttpStacks。

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

关于java - Android: Volley HTTP 补丁请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22411475/

相关文章:

java - 使用 MySQL 和 Java 优化排序功能

Java 以编程方式导入

java - 如何在flutter中检测模拟器或真实设备? (Bluestacks、NoxPlayer 或 LDPlayer)

api - Rest api design : POST to create with duplicate data, would-be IntegrityError/500,什么是正确的?

java集合: Filter using mapped values and then return to initial values

Java-使用交替字符合并两个字符串,同时保留运行

android - 如何在android中创建动态上下文菜单?

android - 使用 DDMS - 确定谁分配了内存

rest - 通过 REST 上传/下载大文件

javascript - NodeJS 未加载外部 javascript