您现在的位置是:主页 > news > 网站怎么做sitemap/百度官方客服

网站怎么做sitemap/百度官方客服

admin2025/6/15 18:18:09news

简介网站怎么做sitemap,百度官方客服,政府网站建设和维护工作总结,南昌建设局网站查询塔吊证Retrofit2 是目前Android开发主流的网络库,RxJava2也是目前开发者使用的比较多用来更优雅实现异步的库,因为最近业务需求有用到这两个库,就简单分享下它的一个实际使用场景—上传文件 集成RxJava2和Retrofit2封装OkHttpManager类封装Retrofit…

网站怎么做sitemap,百度官方客服,政府网站建设和维护工作总结,南昌建设局网站查询塔吊证Retrofit2 是目前Android开发主流的网络库,RxJava2也是目前开发者使用的比较多用来更优雅实现异步的库,因为最近业务需求有用到这两个库,就简单分享下它的一个实际使用场景—上传文件 集成RxJava2和Retrofit2封装OkHttpManager类封装Retrofit…

Retrofit2 是目前Android开发主流的网络库,RxJava2也是目前开发者使用的比较多用来更优雅实现异步的库,因为最近业务需求有用到这两个库,就简单分享下它的一个实际使用场景—上传文件

    • 集成RxJava2和Retrofit2
    • 封装OkHttpManager类
    • 封装RetrofitClient类
    • 定义上传文件接口
    • 构造MultipartBody
    • 自定义RequestBody
    • 具体使用方法
    • 总结

集成RxJava2和Retrofit2

    // Rxcompile rootProject.ext.dependencies["rxjava"]compile rootProject.ext.dependencies["rxandroid"]compile rootProject.ext.dependencies["rxpermissions"]// networkcompile rootProject.ext.dependencies["retrofit"]compile rootProject.ext.dependencies["retrofit-converter-gson"]compile rootProject.ext.dependencies["retrofit-adapter-rxjava2"]compile rootProject.ext.dependencies["logging-interceptor"]

上面我将依赖统一抽取出来了,也建议大家这样做。

具体配置文件在根目录下的config.gradle

ext {android = [compileSdkVersion: 25,buildToolsVersion: '25.0.3',applicationId    : "com.tencent.bugly",minSdkVersion    : 16,targetSdkVersion : 25,javaVersion      : JavaVersion.VERSION_1_7,versionCode      : 1,versionName      : "1.0.0"]def dependVersion = [rxJava             : "2.0.7",rxandroid          : "2.0.1",rxpermissions      : "0.9.3@aar",retrofit           : "2.2.0",okhttp3            : "3.4.1",]dependencies = [// rx"rxjava"                            : "io.reactivex.rxjava2:rxjava:${dependVersion.rxJava}","rxandroid"                         : "io.reactivex.rxjava2:rxandroid:${dependVersion.rxandroid}","rxpermissions"                     : "com.tbruyelle.rxpermissions2:rxpermissions:${dependVersion.rxpermissions}",// network"retrofit"                          : "com.squareup.retrofit2:retrofit:${dependVersion.retrofit}","retrofit-converter-gson"           : "com.squareup.retrofit2:converter-gson:${dependVersion.retrofit}","retrofit-adapter-rxjava2"          : "com.squareup.retrofit2:adapter-rxjava2:${dependVersion.retrofit}",// 网络日志拦截"logging-interceptor"               : "com.squareup.okhttp3:logging-interceptor:${dependVersion.okhttp3}",]
}

这是依赖的部分,集成之后会从maven仓库中将我们需要的库下载到本地,这样我就可以使用了 ,不用说,这些大家都懂。

封装OkHttpManager类

/*** OkHttp管理类.** @author devilwwj* @since 2017/7/12*/
public class OkHttpManager {private static OkHttpClient okHttpClient;/*** 获取OkHttp单例,线程安全.** @return 返回OkHttpClient单例*/public static OkHttpClient getInstance() {if (okHttpClient == null) {synchronized (OkHttpManager.class) {if (okHttpClient == null) {OkHttpClient.Builder builder = new OkHttpClient.Builder();if (BuildConfig.DEBUG) {// 拦截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> T create(Class<T> clz) {return retrofit.create(clz);}/*** 单上传文件的封装.** @param url 完整的接口地址* @param file 需要上传的文件* @param fileUploadObserver 上传回调*/public void upLoadFile(String url, File file,FileUploadObserver<ResponseBody> 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<File> files,FileUploadObserver<ResponseBody> 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";@POSTObservable<ResponseBody> 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<File> files,FileUploadObserver<ResponseBody> 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<ResponseBody> fileUploadObserver;public UploadFileRequestBody(File file, FileUploadObserver<ResponseBody> fileUploadObserver) {this.mRequestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);this.fileUploadObserver = fileUploadObserver;}@Overridepublic MediaType contentType() {return mRequestBody.contentType();}@Overridepublic long contentLength() throws IOException {return mRequestBody.contentLength();}@Overridepublic 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);}@Overridepublic 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 <T> 模板类*/
public abstract class FileUploadObserver<T> extends DefaultObserver<T> {@Overridepublic void onNext(T t) {onUploadSuccess(t);}@Overridepublic void onError(Throwable e) {onUploadFail(e);}@Overridepublic void onComplete() {}// 上传成功的回调public abstract void onUploadSuccess(T t);// 上传失败回调public abstract void onUploadFail(Throwable e);// 上传进度回调public abstract void onProgress(int progress);// 监听进度的改变public void onProgressChange(long bytesWritten, long contentLength) {onProgress((int) (bytesWritten * 100 / contentLength));}
}

ok,到现在完整的代码实现已经说完。

具体使用方法

RetrofitClient.getInstance().upLoadFiles(UploadFileApi.UPLOAD_FILE_URL, files,new FileUploadObserver<ResponseBody>() {@Overridepublic void onUploadSuccess(ResponseBody responseBody) {if (responseBody == null) {LogUtil.e("responseBody null");return;}try {JSONObject jsonObject = new JSONObject(responseBody.string());ArrayList<String> fileIds = new ArrayList<String>();fileIds.add(jsonObject.getString("fileId"));} catch (IOException e) {e.printStackTrace();} catch (JSONException e) {e.printStackTrace();}}@Overridepublic void onUploadFail(Throwable e) {}@Overridepublic void onProgress(int progress) {LogUtil.d(String.valueOf(progress));}});

笔者这里是上传到文件服务器,成功会返回对应的fileId。

总结

通篇代码实现很多,但可以看到使用Retrofit2和RxJava2的结合起来使用还是挺方便的,再也不用自己去控制线程的切换了,也不用去关注http的具体实现,少写了不少代码,实现起来也优雅不少,希望这篇文章能帮助到大家。