Retrofit是由Square公司开发的类型安全HTTP客户端框架,借助动态代理在运行时生成接口实现类,将注解转化为OkHttp请求配置;节省成本通过转换器(Gson/Moshi)自动序列化JSON/XML,内部处理网络请求在主线程返回报文。Retrofit 直译是封装、翻版。他就是对okhttp做了进一步封装,方便使用,它底层的所有请求默认走的都是Okhttp。 所以使用Retrofit必须依赖okHttp。
两者区别:Retrofit是基于App发请求的封装,也就是面向的应用层(比如响应数据的处理和错误处理等),而Okhhtp是对底层网络请求的封装与优化(socket优化,数据压缩,buffer缓存等)。
本文将通过GET/POSTde 基础请求、文件上传、动态URL、缓存、转换器,以及借助OKHttp实现Retrofit请求过程中设置请求头、cookie、超时时间和拦截器都是借助OkHttpClient 等。
1、添加依赖:
使用Retrofit添加的依赖,另外,使用转换器也需要在build.gradle中单独引入,两种转换器通常不必同时使用,根据项目JSON处理需求选择其一即可:
dependencies {implementation 'com.squareup.retrofit2:retrofit:2.9.0'
}
GsonConverterFactory依赖配置:
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.google.code.gson:gson:2.8.8'
MoshiConverterFactory依赖配置:
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.squareup.moshi:moshi:1.14.0' // Moshi
2、业务场景实现
先定义一个接口:
切记这里必须是interface!!!
public interface RequestService {@GET("login/{id}")Call<LoginInfo> login(@Path("id") int userId);@POST("users/new")@Headers("Content-Type: application/json") // 设置请求头Call<ResponseBody> loginPost(@Body LoginInfo loginInfo); // @Body注解表示请求体@Multipart // 表示多部分请求@POST("upload")Call<ResponseBody> uploadFile( @Part("description") RequestBody description, @Part MultipartBody.Part file);// 借助@Url注解,指定完整URL@GETCall<ResponseBody> getCustomUrl(@Url String url);//借助Query注解,添加查询参数@GET("search")Call<ResponseBody> queryData(@Query("q") String query);}
定义实体类 LoginInfo.java :
public class LoginInfo {private String userNmae;private String userPwd;public LoginInfo(String userNmae, String userPwd) {this.userNmae = userNmae;this.userPwd = userPwd;}
}
定义初始化Retrofit的单例工具类 RetrofitUtil.java :
public class RetrofitUtil {private static RetrofitUtil retrofitUtil;private Retrofit retrofit;File httpCacheDirectory = new File(BaseApplication.getContext().getCacheDir(), "responses");int cacheSize = 10 * 1024 * 1024; // 10MBCache cache = new Cache(httpCacheDirectory, cacheSize);private RetrofitUtil(){}public static RetrofitUtil getInstance(){synchronized (RetrofitUtil.class){if (retrofitUtil == null){retrofitUtil = new RetrofitUtil();}return retrofitUtil;}}public <T> T getServer(Class<T> cls, String baseUrl){if (retrofit == null){retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(getClient()).addConverterFactory(GsonConverterFactory.create()).build();}return retrofit.create(cls);}public OkHttpClient getClient(){// 创建OkHttpClientOkHttpClient okHttpClient = new OkHttpClient.Builder()
// .cookieJar().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();// 添加统一请求头request = request.newBuilder().header("Cache-Control", "public, max-age=60").build();return chain.proceed(request);}}).cache(cache).build();return okHttpClient;}
}
注意Retrofit在设置请求头、cookie、超时时间和拦截器都是借助OkHttpClient 来实现。
2.1 Get请求
getTv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int id = 600001;RetrofitUtil.getInstance().getServer(RequestService.class,mUrl).login(id).enqueue(new Callback<LoginInfo>() {@Overridepublic void onResponse(Call<LoginInfo> call, Response<LoginInfo> response) {if (response.isSuccessful()) {LoginInfo loginInfo = response.body(); // 自动解析JSON为User对象}}@Overridepublic void onFailure(Call<LoginInfo> call, Throwable t) {t.printStackTrace();}});}
});
2.2 POST请求
LoginInfo loginInfo = new LoginInfo("Admin", "12345678");
// 发起请求
Call<ResponseBody> call = RetrofitUtil.getInstance().getServer(RequestService.class,mUrl).loginPost(loginInfo);
call.enqueue(new Callback<ResponseBody>() {@Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {// 请求成功}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {// 请求失败}
});
2.3 文件上传
// 准备文件
File file = new File("path/to/file.jpg");
RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpeg"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);// 发起上传请求
RetrofitUtil.getInstance().getServer(RequestService.class,mUrl).uploadFile(RequestBody.create(MediaType.parse("text/plain"), "文件描述"),body).enqueue(new Callback<ResponseBody>() {@Overridepublic void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {//处理上传成功后的逻辑}@Overridepublic void onFailure(Call<ResponseBody> call, Throwable t) {//处理上传失败的逻辑}
});
2.4动态指定URL和添加查询参数
一般来说一个项目中你可能定封装了公共个请求路径和域名,但有个别接口就需要特立独行的地址和传参,此时可以借助@Url和@Query动态的实现。 两个请求也在上面给出的RequestService 这个接口中定义了。
// 使用动态URLCall<ResponseBody> call1 = RetrofitUtil.getInstance().getServer(RequestService.class,mUrl).getCustomUrl("https://api.example.com/custom/path");// 使用查询参数Call<ResponseBody> call2 = RetrofitUtil.getInstance().getServer(RequestService.class,mUrl).queryData("retrofit");
个人总结记录,才疏学浅,如有错误,欢迎指正,多谢。