Retrofit2 & RxJava2实现单文件和多文件上传

本文介绍了如何在Android应用中使用OkHttp和Retrofit进行网络请求,包括设置超时时间、拦截器配置,以及Retrofit的接口定义、MultipartBody构造和自定义RequestBody以支持文件上传功能。还提到使用Gson和RxJava2进行数据处理和回调管理。
摘要由CSDN通过智能技术生成

// 拦截okHttp的日志,如果开启了会导致上传回调被调用两次

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();

interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

builder.addInterceptor(interceptor);

}

// 超时时间

builder.connectTimeout(15, TimeUnit.SECONDS);// 15S连接超时

builder.readTimeout(20, TimeUnit.SECONDS);// 20s读取超时

builder.writeTimeout(20, TimeUnit.SECONDS);// 20s写入超时

// 错误重连

builder.retryOnConnectionFailure(true);

okHttpClient = builder.build();

}

}

}

return okHttpClient;

}

}

这个类主要是获取OkHttpClient示例,设置它的一些参数,比如超时时间,拦截器等等.

封装RetrofitClient类


/**

  • RetrofitClient.

  • @author devilwwj

  • @since 2017/7/12

*/

public class RetrofitClient {

private static RetrofitClient mInstance;

private static Retrofit retrofit;

private RetrofitClient() {

retrofit = RetrofitBuilder.buildRetrofit();

}

/**

  • 获取RetrofitClient实例.

  • @return 返回RetrofitClient单例

*/

public static synchronized RetrofitClient getInstance() {

if (mInstance == null) {

mInstance = new RetrofitClient();

}

return mInstance;

}

private T create(Class clz) {

return retrofit.create(clz);

}

/**

  • 单上传文件的封装.

  • @param url 完整的接口地址

  • @param file 需要上传的文件

  • @param fileUploadObserver 上传回调

*/

public void upLoadFile(String url, File file,

FileUploadObserver fileUploadObserver) {

UploadFileRequestBody uploadFileRequestBody =

new UploadFileRequestBody(file, fileUploadObserver);

create(UploadFileApi.class)

.uploadFile(url, MultipartBuilder.fileToMultipartBody(file,

uploadFileRequestBody))

.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

.subscribe(fileUploadObserver);

}

/**

  • 多文件上传.

  • @param url 上传接口地址

  • @param files 文件列表

  • @param fileUploadObserver 文件上传回调

*/

public void upLoadFiles(String url, List files,

FileUploadObserver fileUploadObserver) {

create(UploadFileApi.class)

.uploadFile(url, MultipartBuilder.filesToMultipartBody(files,

fileUploadObserver))

.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

.subscribe(fileUploadObserver);

}

}

这个是Retrofit客户端类,获取它的单例然后去调用它的上传文件的方法,可以看到我这里封装了两个方法,uploadFile是上传单个文件,uploadFiles方法上传多个文件.

因为我们需要构造一个Retrofit对象,所以这里有一个RetrofitBuilder类:

/**

  • Retrofit构造器.

  • @author devilwwj

  • @since 2017/7/13

*/

public class RetrofitBuilder {

private static Retrofit retrofit;

public static synchronized Retrofit buildRetrofit() {

if (retrofit == null) {

Gson gson = new GsonBuilder().setDateFormat(“yyyy-MM-dd HH:mm:ss”).create();

GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);

retrofit = new Retrofit.Builder().client(OkHttpManager.getInstance())

.baseUrl(AppConfig.HTTP_SERVER)

.addConverterFactory(gsonConverterFactory)

.addCallAdapterFactory(RxJava2CallAdapterFactory.create())

.build();

}

return retrofit;

}

}

可以看到,想构造Retrofit对象是需要获取OkhttpClient实例的。

定义上传文件接口


/**

  • 上传API.

  • @author devilwwj

  • @since 2017/7/12

*/

public interface UploadFileApi {

String UPLOAD_FILE_URL = AppConfig.HTTP_SERVER + “file/upload”;

@POST

Observable uploadFile(@Url String url, @Body MultipartBody body);

}

这里就是Retrofit定义接口的形式,通过注解来表示各个参数,@POST表示发起post请求,@Url表示这是个请求地址,@Body表示这是请求体,关于Retrofit的各种注解的使用这里不多说,大家可以自行了解。

构造MultipartBody


上一步定义好了上传的接口,我们最终是要去构造MultipartBody,这一块就需要跟后台同学进行沟通了,根据接口定义来实现,这里是我们的实现:

/**

  • MultipartBuilder.

  • @author devilwwj

  • @since 2017/7/13

*/

public class MultipartBuilder {

/**

  • 单文件上传构造.

  • @param file 文件

  • @param requestBody 请求体

  • @return MultipartBody

*/

public static MultipartBody fileToMultipartBody(File file, RequestBody requestBody) {

MultipartBody.Builder builder = new MultipartBody.Builder();

JsonObject jsonObject = new JsonObject();

jsonObject.addProperty(“fileName”, file.getName());

jsonObject.addProperty(“fileSha”, Utils.getFileSha1(file));

jsonObject.addProperty(“appId”, “test0002”);

builder.addFormDataPart(“file”, file.getName(), requestBody);

builder.addFormDataPart(“params”, jsonObject.toString());

builder.setType(MultipartBody.FORM);

return builder.build();

}

/**

  • 多文件上传构造.

  • @param files 文件列表

  • @param fileUploadObserver 文件上传回调

  • @return MultipartBody

*/

public static MultipartBody filesToMultipartBody(List files,

FileUploadObserver fileUploadObserver) {

MultipartBody.Builder builder = new MultipartBody.Builder();

JsonArray jsonArray = new JsonArray();

Gson gson = new Gson();

for (File file : files) {

UploadFileRequestBody uploadFileRequestBody =

new UploadFileRequestBody(file, fileUploadObserver);

JsonObject jsonObject = new JsonObject();

jsonObject.addProperty(“fileName”, file.getName());

jsonObject.addProperty(“fileSha”, Utils.getFileSha1(file));

jsonObject.addProperty(“appId”, “test0002”);

jsonArray.add(jsonObject);

LogUtil.d(jsonObject.toString());

builder.addFormDataPart(“file”, file.getName(), uploadFileRequestBody);

}

builder.addFormDataPart(“params”, gson.toJson(jsonArray));

LogUtil.d(gson.toJson(jsonArray));

builder.setType(MultipartBody.FORM);

return builder.build();

}

}

自定义RequestBody


构造MultipartBody是需要去创建每个文件对应的ReqeustBody,但我们这边需要监听到文件上传成功、失败和进度的状态,所以需要去自定义:

/**

  • 上传文件请求body.

  • @author devilwwj

  • @since 2017/7/12

*/

public class UploadFileRequestBody extends RequestBody {

private RequestBody mRequestBody;

private FileUploadObserver fileUploadObserver;

public UploadFileRequestBody(File file, FileUploadObserver fileUploadObserver) {

this.mRequestBody = RequestBody.create(MediaType.parse(“application/octet-stream”), file);

this.fileUploadObserver = fileUploadObserver;

}

@Override

public MediaType contentType() {

return mRequestBody.contentType();

}

@Override

public long contentLength() throws IOException {

return mRequestBody.contentLength();

}

@Override

public void writeTo(BufferedSink sink) throws IOException {

CountingSink countingSink = new CountingSink(sink);

BufferedSink bufferedSink = Okio.buffer(countingSink);

// 写入

mRequestBody.writeTo(bufferedSink);

// 刷新

// 必须调用flush,否则最后一部分数据可能不会被写入

bufferedSink.flush();

}

/**

  • CountingSink.

*/

protected final class CountingSink extends ForwardingSink {

private long bytesWritten = 0;

public CountingSink(Sink delegate) {

super(delegate);

}

@Override

public void write(Buffer source, long byteCount) throws IOException {

super.write(source, byteCount);

bytesWritten += byteCount;

if (fileUploadObserver != null) {

fileUploadObserver.onProgressChange(bytesWritten, contentLength());

}

}

}

}

这里有个RxJava2的Observer的抽象类,主要是用来收到Rxjava2的事件:

/**

  • 上传文件的RxJava2回调.

  • @author devilwwj

  • @since 2017/7/12

  • @param 模板类

*/

public abstract class FileUploadObserver extends DefaultObserver {

@Override

public void onNext(T t) {

onUploadSuccess(t);

}

@Override

public void onError(Throwable e) {

onUploadFail(e);

}

@Override

public void onComplete() {

}

// 上传成功的回调

public abstract void onUploadSuccess(T t);

// 上传失败回调

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

外链图片转存中…(img-IsiWz0wz-1713407172034)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

[外链图片转存中…(img-EqZhfM7L-1713407172035)]

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

[外链图片转存中…(img-Yo2ormWa-1713407172036)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OkHttp 是一个用于进行网络请求的开源框架,它基于 Java 的 HttpURLConnection 类进行封装,提供了更简、更强大的网络请求功能。 Retrofit2 是一个基于 OkHttp 的网络请求框架,它通过注解和反射的方式,将网络请求接口转换成具体的网络请求动作。同时,Retrofit2 也提供了许多强大的功能,例如请求头、请求体的自定义、请求解析器的设置、请求拦截器等。 RxJava2 是一个响应式编程框架,它提供了一种更优雅和简洁的处理异步操作的方式。通过使用观察者模式和链式调用的方式,我们可以简化对多个异步操作的管理和处理,同时提供了丰富的操作符,用于处理和组合异步数据流。 MVVM 是一种用于设计和实现用户界面的架构模式。它将应用程序的界面逻辑和数据逻辑分开,并通过数据绑定机制实现二者之间的通信。在 MVVM 中,Model 层负责数据的获取和处理,View 层负责界面的显示和用户输入的处理,而 ViewModel 则负责衔接二者之间的通信。 通过将 OkHttp、Retrofit2RxJava2 和 MVVM 结合使用,我们可以构建出一个功能强大、性能优秀、响应迅速的网络请求和数据处理框架。OkHttp 提供了稳定可靠的网络请求功能,Retrofit2 则提供了简易用的网络接口转换方式,RxJava2 则提供了异步数据处理和链式调用的能力,而 MVVM 则提供了一种清晰的架构模式,使得我们可以更好地组织应用程序的逻辑。总的来说,这些技术和框架的结合能够让我们在开发中更加高效、稳定和灵活。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值