时间关系,本文就 Retrofit 2.0的简单使用 做讲解 至于原理以后有空再去分析
项目全面、简单、易懂 地址:
关于Retrofit 2.0的简单使用如下: https://gitee.com/bimingcong/MyRetrofit
private void initGet() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://v.juhe.cn/") .addConverterFactory(GsonConverterFactory.create()) .build(); GetService service = retrofit.create(GetService.class); final Call<GetBean> call = service.getString3("toutiao", "shehui", "d05b58fa6901ad9bed77a1ef08bd6ccb"); call.enqueue(new Callback<GetBean>() { @Override public void onResponse(Call<GetBean> call, Response<GetBean> response) { if (response.isSuccessful()) { GetBean = response.body(); } } @Override public void onFailure(Call<GetBean> call, Throwable t) { } }); }
其中的GetService是干嘛的 里边的@query其实可以理解为get请求url ?后边那一串参数的键值对
public interface GetService { //直接拼接,记得加问号 @GET("toutiao/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb") Call<GetBean> getString(); //{name}可以最简单的将其理解为路径替换块,用”{}”表示,与注解@path配合使用 ,为了解耦,参数name==toutiao @GET("{name}/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb") Call<GetBean> getString2(@Path("name") String name); //对于@GET来说,参数信息是可以直接放在url中上传的。那么你马上就反应过来了,这一样也存在严重的耦合! //于是,就有了@query @GET("{name}/index") Call<GetBean> getString3(@Path("name") String name, @Query("type") String type , @Query("key") String key); //假设我要在参数中上传10个参数呢?这意味着我要在方法中声明10个@Query参数?当然不是! //Retrofit也考虑到了这点,所以针对于复杂的参数上传,为我们准备了@QueryMap @GET("{name}/index") Call<GetBean> getString4(@Path("name") String name, @QueryMap HashMap<String, String> hashMap); //一般Get都没有请求体,所以直接获取接口网址即可 Url动态化 @GET() Observable<ResponseBody> getString5(@Url String url); }
针对Post请求 其中的@Field 其实可以理解为 post要提交的 参数键值对 其中还有单个文件 以及多个文件的上传
public interface PostService { @FormUrlEncoded @POST("toutiao/index") Call<PostBean> postString(@Field("type") String type, @Field("key") String key); // Post表单提交-多个参数-@FieldMa @FormUrlEncoded @POST("toutiao/index") Call<PostBean> postString2(@FieldMap HashMap<String, String> params); // Post文件提交 ,每个键值对都需要用@Part注解键名字 //Multipart 支持文件上传 @Multipart @POST("https://pan.baidu.com/disk/home?#/all?vmode=list&path=%2Fas") Call<TestBean> postFile(@Part("photo";filename="test.png"") RequestBody body); @Multipart @POST("xxxx") Call<TestBean> postFile2(@PartMap HashMap<String, RequestBody> bodyMap, @Field("token") String token); }
对应的例子如下:
//当我获取数据成功后要做什么处理 public interface OnSuccessListener { void onSuccess(Object o); void onFaile(); }
//提供一些方法去调用service实体类的方法,RequestBody上传单个文件 public void uploadFile(RequestBody body, final OnSuccessListener listener) { Call<TestBean> call = mService.postFile(body); call.enqueue(new Callback<TestBean>() { @Override public void onResponse(Call<TestBean> call, Response<TestBean> response) { listener.onSuccess(response); } @Override public void onFailure(Call<TestBean> call, Throwable t) { listener.onFaile(); } }); }
转换器:
至于自定义转换器 就是 下边这个参数
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://v.juhe.cn/") .addConverterFactory(GsonConverterFactory.create()) .build();
比如我们只希望返回数据是String类型,我们需要自定义一个ConverterFactory
public class StringConverFactory extends Converter.Factory { public static StringConverFactory create() { return new StringConverFactory(); } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { Log.d("wyz", "读取数据:responseBodyConverter" + type); if (type == String.class) {//此处的Type类型 我的理解是一开始Call对象参数定义的返回值类型 Log.d("wyz", "执行开始"); return StringResponseBodyConverter.INSTANCE; } return null; } @Nullable @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { Log.d("wyz", "请求数据类型:" + type); if (type == NetRequest.class){ } return null; }
final class StringResponseBodyConverter implements Converter<ResponseBody, String> { public static final StringResponseBodyConverter INSTANCE =new StringResponseBodyConverter(); @Override public String convert(ResponseBody value) throws IOException { Log.d("wyz", "转换开始:" + value); String s = value.string(); return s; }
最后将 ConvertFactory设置到Retrofit实例中就可以了
retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(getOkHttpClient()) .addConverterFactory(StringConverFactory.create())
日志:
最后对于 红色的部分是添加一个自定义的Client 此处主要是对相应级别的日志去拦截
在retrofit2.0中是没有日志功能的。但是retrofit2.0中依赖OkHttp,所以也就能够通过OkHttp中的interceptor来实现实际的底层的请求和响应日志。在这里我们需要修改上一个retrofit实例,为其自定自定义的OkHttpClient。代码如下:
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .build(); Retrofit retrofit = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(okHttpClient) .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build();
需要添加依赖:
compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
效果:
更加详细的Demo 可以去我的开源中国里看 https://gitee.com/bimingcong/MyRetrofit