前言
目前Android 请求框架层出不穷,主流的框架有一下几种,
Android-Async-Http、
Volley、
OkHttp、
Retrofit
而Retrofit备受大家的喜爱,当然也是因为它确实好用。
本文就针对Retrofit进行简单的封装,主要对自己近一年对该框架的使用情况进行整理。这里不再讲解原生retrofit的使用。
正式开始
客户端的封装:
/**
* @author KangLong
* date 2017/5/8
* description 快速 构建Retrofit请求类
*/
public class MyRetrofitClient {
public static String baseUrl = BaseApiService.BASE_URL_DAFULT;
private static final long TIMEOUT = 10;
private static final String TAG = "MyRetrofitClient";
private Retrofit retrofit;
private static Context mContext;
private OkHttpClient mOkHttpClient;
public final static Map<String, String> baseUrlMap = new HashMap<>();
static {
baseUrlMap.put("zhihu", BaseApiService.BASE_URL_ZHIHU);
baseUrlMap.put("baidu", BaseApiService.BASE_URL_BAIDU);
}
public static MyRetrofitClient getInstance(Context context) {
if (context != null) {
mContext = context;
}
return SingletonHolder.INSTANCE;
}
private static MyRetrofitClient getInstance(Context context, String url) {
if (context != null) {
mContext = context;
}
return new MyRetrofitClient(context, url);
}
/**
* 用于自定义url的请求和添加token的请求
*
* @param context 上下文
* @param url 自定义baseUrl
* @param headers 自定义添加的header
* @return
*/
private static MyRetrofitClient getInstance(Context context, String url, Map<String, String> headers) {
if (context != null) {
mContext = context;
}
return new MyRetrofitClient(context, url, headers);
}
/**
* 创建内部类单利
*/
private static class SingletonHolder {
private static MyRetrofitClient INSTANCE = new MyRetrofitClient(mContext);
}
private MyRetrofitClient() {
}
/**
* 构造函数,用于初试化
*
* @param context
*/
private MyRetrofitClient(Context context) {
this(context, null);
}
private MyRetrofitClient(Context context, String url) {
this(context, url, null);
}
private MyRetrofitClient(Context context, String url, Map<String, String> headers) {
if (TextUtils.isEmpty(url)) {
url = baseUrl;
}
File mFile = new File(context.getCacheDir() + "http");//储存目录
long maxSize = 10 * 1024 * 1024; // 10 MB 最大缓存数
Cache mCache = new Cache(mFile, maxSize);
mOkHttpClient = new OkHttpClient.Builder()
//添加Cookie管理,不需要管理可以不加,token在Cookie中的时候需要添加
.cookieJar(new CookieManger(context.getApplicationContext()))
//添加统一的请求头
.addInterceptor(new BaseInterceptor(headers))
//添加base改变拦截器
.addInterceptor(new BaseUrlInterceptor())
//添加缓存拦截器
.addNetworkInterceptor(new CaheInterceptor(context))
//打印请求信息(可以自定义打印的级别!!)
.addNetworkInterceptor(new HttpLoggingInterceptor(/*message -> Log.e(TAG, message)*/).setLevel(HttpLoggingInterceptor.Level.BODY))
//相关请求时间设置
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
//添加缓存
.cache(mCache)
.connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS))
// 这里你可以根据自己的机型设置同时连接的个数和时间,我这里8个,和每个保持时间为15s
.build();
retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(mOkHttpClient)
//添加转换器String
.addConverterFactory(ScalarsConverterFactory.create())
//这里是转换器 这里采用Gson做转换器
.addConverterFactory(GsonConverterFactory.create())
//添加RXjava做适配器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
/**
* 用于构建请求代理,BaseApiService中没有包含时可以用这个
*
* @param service
* @param <T>
* @return
*/
public <T> T createService(Class<T> service) {
if (service == null) {
throw new RuntimeException("Api service is null!");
}
return retrofit.create(service);
}
/**
* 通过代理构建接口
*
* @return
*/
public BaseApiService createService() {
return retrofit.create(BaseApiService.class);
}
}
简单使用:没有参数
在baseApiService中配置
/**
* (示例无参数请求)
* 这里用默认回调
* 获取版本号
*
* @param
* @return
*/
@Headers({URL_NAME + BASE_URL_ZHIHU})
@GET("/api/4/version/android/2.3.0")
Call<BaseResponse<Resond>> getVersionDefult();
使用客户端调用
MyRetrofitClient.getInstance(this)
.createService()
.getVersionDefult()
.enqueue(new Callback<BaseResponse<Resond>>() {
@Override
public void onResponse(Call<BaseResponse<Resond>> call, Response<BaseResponse<Resond>> response) {
textView.setText(response.body().toString());
}
@Override
public void onFailure(Call<BaseResponse<Resond>> call, Throwable t) {
}
});
[图片上传中...(image-935289-1538296683823-6)]
带参数,配合Rxjava
在baseApiService中配置
/**
* 只有一个参数
*
* @param mobile 手机号
* @return
*/
@GET("/fitness/coach/login/code.jhtml")
Observable<BaseResponse<String>> getVerificatCode(@Query("mobile") String mobile);
[图片上传中...(image-103b43-1538296683823-5)]
调用方式
MyRetrofitClient.getInstance(this)
.createService()
.getVerificatCode("18380426497")
.compose(RxHelper.io_main(this))
.subscribe(new BaseObserver<String>(this) {
@Override
protected void onSuccess(String value) {
textView.setText(value.toString());
}
@Override
protected void onBefore(Disposable d) {
}
@Override
protected void onFailure(String message) {
}
});
[图片上传中...(image-9e2353-1538296683823-4)]
上传图片
在baseApiService中配置
/**
* 上传资源的封面
*
* @param body 文件
* @return
*/
@POST("/fitness/coach/member/uploadCover.jhtml")
Observable<BaseResponse<String>> uploadCover(@Body RequestBody body);
[图片上传中...(image-9b3cb9-1538296683823-3)]
调用方式
File file = new File("/你的文件路径");
RequestBody mBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", "cover.jpg", RequestBody.create(MediaType.parse("image/*"), file))
.build();
MyRetrofitClient.getInstance(this)
.createService()
.uploadCover(mBody)
.compose(RxHelper.io_main(this))
.subscribe(new BaseObserver<String>(this) {
@Override
protected void onSuccess(String value) {
textView.setText(value.toString());
}
@Override
protected void onBefore(Disposable d) {
}
@Override
protected void onFailure(String message) {
}
});
[图片上传中...(image-99c2c7-1538296683823-2)]
上传多张图片/视频/或者图文同时传
在baseApiService中配置
/**
* @param body
* @return //难度星级
* private int star
* <p>
* //时长
* private Integer duration
* <p>
* private TrainType trainType
* //封面
* private String cover
* //标题
* private String title
* private String content
* private String file;
* public enum TrainType
* {
* //5分钟器械
* FIVE_MINI_INSTREMENT,
* //5分钟徒手
* FIVE_MINI_UNARMED,
* //5分钟柔韧
* FIVE_MINI_PLIABLE,
* }
*/
@POST("/fitness/coach/member/uploadVideo.jhtml")
Observable<BaseResponse<String>> uploadCourse(@Body RequestBody body);
[图片上传中...(image-5294a5-1538296683823-1)]
调用方式
File file1 = new File("/你的文件路径");
File file2 = new File("/你的文件路径");
File file3 = new File("/你的文件路径");
File file4 = new File("/你的文件路径");
File file5 = new File("/你的文件路径");
RequestBody mBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file1", file1.getName(), RequestBody.create(MediaType.parse("video/*"), file1))
.addFormDataPart("file2", file2.getName(), RequestBody.create(MediaType.parse("video/*"), file2))
.addFormDataPart("file3", file3.getName(), RequestBody.create(MediaType.parse("video/*"), file3))
.addFormDataPart("file4", file4.getName(), RequestBody.create(MediaType.parse("video/*"), file4))
.addFormDataPart("file5", file5.getName(), RequestBody.create(MediaType.parse("video/*"), file5))
.addFormDataPart("duration", 10 + "")
.addFormDataPart("star", String.valueOf(5))
.addFormDataPart("trainType", "trainType")
.addFormDataPart("content", "content")
.addFormDataPart("cover", "cover")
.addFormDataPart("title", "title")
.build();
MyRetrofitClient.getInstance(this)
.createService()
.uploadCourse(mBody)
.compose(RxHelper.io_main(this))
.subscribe(new BaseObserver<String>(this) {
@Override
protected void onSuccess(String value) {
textView.setText(value.toString());
}
@Override
protected void onBefore(Disposable d) {
}
@Override
protected void onFailure(String message) {
}
});
[图片上传中...(image-a19128-1538296683821-0)]
总结
封装中还包含了动态改变BaseUrl,动态添加header,中断请求等等常用功能。后会添加MVP+Dagger2的方式封装。
关于特别的方式,及文件详情见demo,有问题欢迎issue,喜欢请star支持一下哟!