【问题标题】:Can a request be cancelled when it is already in the getBody() method?当请求已经在 getBody() 方法中时,可以取消请求吗?
【发布时间】:2016-04-07 15:53:29
【问题描述】:

我有一个 MultipartPostRequest,它在 getBody() 方法中实现了进度计数功能。所以我在通知栏中显示进度。当用户点击显示进度的通知时,它应该被取消,就像 Facebook 实现它的方式一样。

我尝试在实际的 Request 对象上使用 Request.cancel()RequestQueue.cancelAll(Object tag),但请求仍未被取消。

我读到无法取消正在进行的请求,但在这种情况下,它仍然只是在 getBody() 方法中,所以我认为(我不太确定)它应该被取消,对吧?因为我还记录了isCancelled() 方法的返回,是的,当单击通知时它确实返回true,并且在返回上传请求进度的方法中调用日志,这意味着它在@987654327 @ 方法。

但令人惊讶且令人沮丧的是,请求仍然通过,因为它仍然返回结果!

有没有办法解决这个问题?或者有没有办法像 Facebook 那样实现它?如果可以的话,我很乐意为此提供赏金。

我正在使用这个答案中的课程:https://stackoverflow.com/a/28144660/1744379

由于某些情况,我无法分享我的代码。但是这个类正是我使用的,我只是做了一些小的调整。 CountingOutputStream 的位置与CountingOutputStreamMultipartPostProgressListener 相同。因此,检查isCancelled 方法的Log 位于我在Service 中实现的transferred 方法中

【问题讨论】:

  • 嗨!我的回答对你的问题有用吗?
  • 您好,很抱歉客户放弃了这个想法。但不幸的是,没有答案没有奏效。但有效的是,在 getBody() 方法结束时,我通过isCancelled 方法检查了请求是否已经取消,然后我会给请求一个空的byte[],从而让服务器返回一个错误我和我会默默地让它过去
  • 在我的示例项目中,当调用 cancelUpload 时,文件在大约 3-5 秒后停止上传。当然,上传到服务器的数据仍然存在(比如一个2MB的文件,上传大约1MB)
  • 是的,但这里的问题是上传速度非常快,因为我们的限制只有 5mb。所以大约 3-5 秒就足以完成上传

标签: android facebook httprequest android-volley cancellation


【解决方案1】:

IMO,您可以参考以下内容:

首先,需要的变量:

public class MainActivity extends AppCompatActivity {
    private Context mContext = this;
    private Uri mFileUri;
    private String mFilePath;
    private ImageView mImagePreview;
    private ProgressBar mProgressBar;
    StringRequest mStringRequest;
    private long mFileLength;
    private MultipartProgressListener multipartProgressListener;
    ...

假设您获得了从手机的相机(图库)文件夹中选择图像文件的代码,并成功获取了文件路径(mFilePath)。

private void cancelUpload(){    
    mStringRequest.cancel();
}

private void uploadFile(){
    mProgressBar.setProgress(0);
    String url = "http://yourserver/fileupload";
    MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

    if (mFilePath != null) {
        File file = new File(mFilePath);
        if (file.exists()) {
            mFileLength = file.length();
            FileBody fileBody = new FileBody(file);
            entityBuilder.addPart("file", fileBody);

            final HttpEntity httpEntity = entityBuilder.build();

            mStringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    mFilePath = "";
                    Log.i("Multipart", response);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Multipart", error.toString());
                }
            }) {
                @Override
                public String getBodyContentType() {
                    return httpEntity.getContentType().getValue();
                }

                @Override
                public byte[] getBody() throws AuthFailureError {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    try {
                        //httpEntity.writeTo(bos);
                        httpEntity.writeTo(new CountingOutputStream(bos, mFileLength,
                                multipartProgressListener));
                    } catch (IOException e) {
                        Log.e("Multipart", e.toString());
                    }
                    return bos.toByteArray();

                }
            };
            mStringRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 5, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
            VolleySingleton.getInstance(mContext).addToRequestQueue(mStringRequest);
        }
    }
}

以下代码来自您问题中的链接,我做了一些更新(请注意它们不再是static

    public interface MultipartProgressListener {
        void transferred(long transfered, int progress);
    }

    public class CountingOutputStream extends FilterOutputStream {
        private final MultipartProgressListener progListener;
        private long transferred;
        private long fileLength;

        public CountingOutputStream(final OutputStream out, long fileLength,
                                    final MultipartProgressListener listener) {
            super(out);
            this.fileLength = fileLength;
            this.progListener = listener;
            this.transferred = 0;
        }

        public void write(byte[] b, int off, int len) throws IOException {
            Log.i("isCanceled", String.valueOf(mStringRequest.isCanceled()));
            if (!mStringRequest.isCanceled()) {
                out.write(b, off, len);
                if (progListener != null) {
                    this.transferred += len;
                    int prog = (int) (transferred * 100 / fileLength);
                    this.progListener.transferred(this.transferred, prog);
                }
            } else {
                Log.w("Multipart", "Request canceled!");
                out.flush();
                out.close();
            }
        }

        public void write(int b) throws IOException {
            if (!mStringRequest.isCanceled()) {
                out.write(b);
                if (progListener != null) {
                    this.transferred++;
                    int prog = (int) (transferred * 100 / fileLength);
                    this.progListener.transferred(this.transferred, prog);
                }
            } else {
                Log.w("Multipart", "Request canceled!");
                out.flush();
                out.close();
            }
        }
    }

P/S:你应该选择大文件大小:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-22
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 2018-12-16
    相关资源
    最近更新 更多