okhttp+Retrofit 上传进度监听

  • 效果图


    GIF 2021-7-1 10-34-26.gif

分为三类来说
1,单独使用okhttp 上传,监听上传进度
2,使用okhttp + retrofit上传,监听上传进度
3,使用okhttp + retrofit上传,监听上传进度 多文件 统一进度

方法1 okhttp 的使用

最简单的使用

Request request = new Request.Builder()
                            .addHeader("Authorization", "xxx")
                            .url(mNewUploadUrl)
                            .post(multipartBody)
                            .build();

                    Response response = mOkHttpClient.newCall(request).execute();
                    ResponseBody body = response.body();
                    String result = body.string();

这里没有料,为啥呢? 因为监听进度在RequestBody 中,这个就是上传 的时候的参数。

因此重写他好了。。。

public class ProgressRequestBody extends RequestBody {
  ..........略

@Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (mBufferedSink == null) {
            mBufferedSink = Okio.buffer(new CountingSink(sink));
        }
        try {
            mDelegate.writeTo(mBufferedSink);
            // 这里已忘记
            mBufferedSink.flush();
        } catch (IOException e) {
            e.printStackTrace();
            for (int i = 0; i < mListeners.length; i++) {
                mListeners[i].onError(mProgressInfo.getId(), e);
            }
            throw e;
        }
    }

protected final class CountingSink extends ForwardingSink {

  @Override
        public void write(Buffer source, long byteCount) throws IOException {
            
            if (mProgressInfo.getContentLength() == 0) { //避免重复调用 contentLength()
                mProgressInfo.setContentLength(contentLength());
            }
            这里就上传的字节长度了。。。
            totalBytesRead += byteCount;
}
}

  ..........略
}

我只写主要代码了,写太多了看反而记不住。
进度就是写入的除总的长度就是进度了,可以一秒钟中更新一下ui就可以了。。。

这个是实现。

怎么用。
在 mNewUploadUrl 中做手脚。
在加入url 的时候把监听创立

 List<ProgressListener> listeners = mRequestListeners.get(key);
            return request.newBuilder()
                    .method(request.method(), new ProgressRequestBody(mHandler, request.body(), listeners, mRefreshTime))
                    .build();

这个就是ok http 里面的。

mOkHttpClient = ProgressManager.getInstance().with(new OkHttpClient.Builder())
                .build();

String mNewUploadUrl = ProgressManager
                .getInstance()
                .addDiffRequestListenerOnSameUrl("http://192.168.1.67:8016/api/common/upload", "", getUploadListener());

进程

private ProgressListener getUploadListener() {
        return new ProgressListener() {
            @Override
            public void onProgress(ProgressInfo progressInfo) {
                progress = progressInfo.getPercent();
                if (progress < 100) {
                    intent.putExtra("type", UpStype.UPING.getCode());
                    intent.putExtra("progress", progress);
                    sendBroadcast(intent);
                }
            }

            @Override
            public void onError(long id, Exception e) {
                intent.putExtra("type", UpStype.ERROR.getCode());
                sendBroadcast(intent);
                ToastUtils.show("上传失败" + e.getMessage());
            }
        };
    }

方法2 使用okhttp + retrofit上传,监听上传进度

同理,okhttp 里面必少不了 okhttp的配置

okhttp 配置完了就是retrofit

retrofit简单实用

Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(mNewUploadUrl)
                        .client(mOkHttpClient)
                        .build();

                ServiceApi daoServiceApi = retrofit.create(ServiceApi.class);
                retrofit2.Call<ResponseBody> call = daoServiceApi
                        .uploadAttachments(requestBody);

                intent.putExtra("type", UpStype.UPING.getCode());
                intent.putExtra("progress", 0);
                sendBroadcast(intent);

                call.enqueue(new Callback<ResponseBody>() {

                    @Override
                    public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                        ResponseBody body = response.body();
                        String result = null;
                        try {
                            result = body.string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (response.isSuccessful()) {
                            ToastUtils.show("上传成功:" + result);
                            intent.putExtra("progress", 100);
                            intent.putExtra("type", UpStype.FINISH.getCode());
                            sendBroadcast(intent);
                        } else {
                            intent.putExtra("type", UpStype.ERROR.getCode());
                            sendBroadcast(intent);
                            ToastUtils.show("上传失败" + result);
                        }
                        System.out.println("结果:" + result);
                    }

                    @Override
                    public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
                        intent.putExtra("type", UpStype.ERROR.getCode());
                        sendBroadcast(intent);
                        ToastUtils.show("上传失败" + t.getMessage());
                    }
                });
public interface ServiceApi {
    @Multipart
    @POST("xx/xxx/xxx")
    Call<ResponseBody> uploadAttachments(
            @Query("file") RequestBody requestBody 
    );
}

无参数上传 单个文件

  RequestBody requestBody =
                        RequestBody.create(MediaType.parse("image/png"), file);

这个就是Retrofit 的使用了。。

监听在okhttp 里面。。所以这个没有写太多了。。。

方法三 使用okhttp + retrofit上传,监听上传进度多文件

public interface DaoServiceApi {
    @Multipart
    @POST("sounds/xxx/xxx")
    Call<ResponseBody> uploadAttachments(
            @Query("xx") String xx,
            @Query("xx") String xx,
            @Query("xx") String xxx,
            @Part List<MultipartBody.Part> file
    );
}

主要是参数

equestBody requestBody =
RequestBody.create(MediaType.parse("image/png"), file);
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
builder.addFormDataPart("files", file.getName(), requestBody);
就是循环出来的
List<MultipartBody.Part> parts = builder.build().parts();

            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(mNewUploadUrl)
                    .client(mOkHttpClient)
                    .build();

            DaoServiceApi daoServiceApi = retrofit.create(DaoServiceApi.class);
            retrofit2.Call<ResponseBody> call = daoServiceApi
                    .uploadAttachments("7", "xx", "sss", parts);
循环出来的part

![微信截图_20210701120047.png](https://upload-images.jianshu.io/upload_images/1309984-e083b3ef23f736a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



### 其它。。
第三方的 EasyHttp 
上传下载都有进度。不用自己去封装了。。。
还有监听使用https://juejin.cn/post/6844903481057230856

另外,代码不全,别 给您造成疑惑了。。


我主要是做的,在一个页面中上传,启动服务上传,大的文件,让他上传去了,我还可以继续浏览其它的东西。

成功了在发送通知 给用户UI 就行了。

例如抖音里面上传视频。

推荐阅读更多精彩内容