Retrofit使用教程

Retrofit的作用: turns your HTTP API into a Java interface.意思就是讲请求转为java接口一样的使用方式。

1. 添加依赖

compile ‘com.squareup.retrofit2:retrofit:2.3.0’//
compile ‘com.squareup.retrofit2:converter-gson:2.3.0’//gson转换

retrofit2内置了okhttp,可以不用依赖okhttp,但是可以使用自己的okhttp设置:

Retrofit retrofit = new Retrofit.Builder()
                .client(AppOkhttpClient.create())//添加我的OkhttpClient
                .baseUrl(BaseUrl)
                .addConverterFactory(StringResponseConverterFactory.create("utf-8"))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

Note: 这里注意的是addConverterFactory是添加数据转换器,返回的数据是什么格式的,根据这个转换器动态选择,上面的是添加我自己写的要求返回的是String的转换器。addCallAdapterFactory是添加回调适配器,上面我添加的是RxJava2回调适配器,那么请求方法界面是返回Observable,不添任何回调适配器,使用的是Call回调。

public interface ApiTestService {
    @GET("/")
    Call<String> fetchGithub();//不添加任何适配器,默认的是Call回调
    @GET("/")
    Observable<String> fetchGithub1();//添加RxJava适配器,返回的回调是Observer
}

如果使用默认的回调适配器,使用如下:

Retrofit retrofit = new Retrofit.Builder()
               .client(AppOkhttpClient.create())//添加我的OkhttpClient
               .baseUrl(BaseUrl)
               .addConverterFactory(StringResponseConverterFactory.create("utf-8"))
               .build();
       ApiTestService apiTestService = retrofit.create(ApiTestService.class);
       Call<String> call = apiTestService.fetchGithub();
       call.enqueue(new Callback<String>() {
           @Override
           public void onResponse(Call<String> call, Response<String> response) {
               NetLogger.log(response.body().toString());
           }

           @Override
           public void onFailure(Call<String> call, Throwable t) {
               NetLogger.log("onError:" + t.toString());
           }
       });

使用了RxJava回调适配器,使用如下:

ApiTestService apiTestService = retrofit.create(ApiTestService.class);
        Observable<String> observable = apiTestService.fetchGithub1();
        observable.subscribe(new Observer<String>() {
         ...
        });

2.创建HTTP Java interface:

public interface RetrofitService {
    @GET("Data")
    Call<ClassRoomUseTimeInOneMonthBean> getRoomUseData();
}

3.获取接口进行使用

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.2.179:8004/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitService service = retrofit.create(RetrofitService.class);
        Call<ClassRoomUseTimeInOneMonthBean> call = service.getRoomUseData();

获取到call后进行异步请求,跟okhttp使用方式一样:

  call.enqueue(new Callback<ClassRoomUseTimeInOneMonthBean>() {
    ...
        });

注意的是,如果没有addConverterFactory会可能报以下异常,这是因为返回接口时使用了ClassRoomUseTimeInOneMonthBean数据格式返回,但是接口返回数据没有处理就进行返回,所以会报转换异常,需要添加数据转换工厂进行数据转换处理:

retrofitjava.lang.IllegalArgumentException:
Unable to create converter for c

这里可以创建自己的数据转换工厂,比如创建StringConverterFactory,将返回的数据转换为字符串数据返回:


public class StringConverterFactory  extends Converter.Factory {

    public static StringConverterFactory create() {
        return new StringConverterFactory();
    }

    private StringConverterFactory() {

    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new StringResponseBodyConverter();//返回响应数据转换
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new StringRequestBodyConverter();//发送请求数据转换
    }
}

StringRequestBodyConverter 将请求的字符串数据写出 :

public class StringRequestBodyConverter  implements Converter<String, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    StringRequestBodyConverter() {
    }

    @Override public RequestBody convert(String value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        writer.write(value);
        writer.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

StringResponseBodyConverter响应数据转换为字符串:

public class StringResponseBodyConverter implements Converter<ResponseBody, String> {
    @Override
    public String convert(ResponseBody value) throws IOException {
        try {
            return value.string();
        } finally {
            value.close();
        }
    }
}

如果我们需要转换的不是字符串,可能是一种特定格式的数据,比如StringToObjectFactory:

public class StringToObjectFactory extends Converter.Factory {
    private String tag = "StringToObjectFactory";

    public static StringToObjectFactory create() {
        return new StringToObjectFactory();
    }
    private StringToObjectFactory() {

    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new Converter<ResponseBody, ApiOutBean<String>>() {
            @Override
            public ApiOutBean<String> convert(ResponseBody value) throws IOException {
                String data = value.string()+ "";
                ApiOutBean<String> ob = new ApiOutBean<>();
                try {//我们在这里捕捉数据转换的异常
                    ob = new Gson().fromJson(data, ob.getClass());
                }catch (Exception e){
                    Logger.log(tag,""+e.toString());
                    Logger.log(tag,"data:"+data);
                }
                return ob;
            }
        };
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new StringRequestBodyConverter();
    }
}

如果我们不捕捉异常,会回调onFail,也可以通过捕捉异常获取到具体的异常信息,比如捕捉打印出现以下异常:

StringToObjectFactory:com.google.gson.JsonSyntaxException: >java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at >line 1 column 1 path $
StringToObjectFactory:data:

这时可以通过解析获取具体的信息。
也可以使用GsonConverterFactory, 我个人觉得GsonConverterFactory隐藏的比较死,不好查看异常情况。

4. Retrofit各类请求方式:

参考来源:http://square.github.io/retrofit/

  1. get查询:
 @GET("Data/RoomsLessonsEachDay")
    Call<ClassRoomUseTimeInOneMonthBean> getRoomUseDataGuery(@Query("time") String time);

// 多参数可以用map传递
  @GET("Data/RoomsLessonsEachDay")
    Call<ClassRoomUseTimeInOneMonthBean> getRoomUseDataGuery(@QueryMap Map<String, String> options);
  1. 单纯get获取数据:
@GET("Data/RoomsLessonsEachDay")
    Call<ClassRoomUseTimeInOneMonthBean> getRoomUseData();
  1. get指定路径参数:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
  1. post字符串:
 @POST("R/Announce")
    Call<String> addNoticeByBody(@Body String p);
  1. post表单:
    @FormUrlEncoded
    @POST("R/Announce")
    Call<String> addNoticeByForm(@Field("RoomID") String RoomID, @Field("Announce") String Announce);
}
  1. 添加头部信息:
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
  1. 结合rxJava使用

依赖:

    compile 'io.reactivex.rxjava2:rxjava:2.1.7'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'//android项目可以加上这个
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//retrofit需要添加rxJava适配器

初始化时:

Retrofit retrofit = new Retrofit.Builder()
              .addConverterFactory(StringToObjectFactory.create())//添加数据转换工厂
              .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//与rxjava绑定的适配器
              .baseUrl(BASE_URL)
              .build();

retrofitService:


     @Headers({
            "context: mobile",
            "version: 4"
    })

    @GET("data/Rank")
    Observable<ApiOutBean<String>> getResourcesRank(
            , @Query("UserID") String UserID
            , @Query("UserType") int UserType
            , @Query("Start") String startTime
            , @Query("End") String endTime);

使用:

  Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://192.168.2.179:8004/api/")
                .addConverterFactory(StringConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        RetrofitService service = retrofit.create(RetrofitService.class);
        Observable<ApiOutBean<String>> o = service.getResourcesRank(...);

         o.subscribe(new Observer<ApiOutBean<String>>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull ApiOutBean<String> s) {
                Logger.log("onNext", "s:"+s.toString());
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Logger.log("onError", "s:"+e.toString());
            }

            @Override
            public void onComplete() {

            }
        });

如果StringConverterFactory里没有捕捉转换异常,会回调onError方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值