Retrofit 网络框架

简单介绍

Retrofit发送网络请求通过okHttp,okhttp的诸多好处与内部实现机制,相对于直接使用okhttp的好处在于,它支持对Response接收数据进行解析,支持RxJava。

Retrofit和Volley一样,网络请求任务在背后线程中进行,返回结果的处理(或者说回调方法)在UI线程中执行。

此外这里给出Retrofit2相对于Retrofit1的改进

支持了在一个类型中的同步和异步,同时,一个请求也可以被真正地终止;Retrofit1之前是分开的,即需要定义两个方法

每一个 call 对象实例只能被调用一次,request 和 response 都是一一对应的;若需多次重复请求,则建议每次请求前clone一个call对象

Response 对象增加了:响应码(the reponse code),响应消息(the response message),以及读取相应头(headers)

@Url ,允许你直接传入一个请求的 URL,定义如下方法

@GET

Call> repoContributorsPaginate(@Url String url);

动态 URL Parameter

String links = response.headers().get("Link");
Call> nextCall = gitHubService.repoContributorsPaginate(nextLink);

基本使用

一、引入依赖

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2' 
compile 'com.squareup.okhttp3:okhttp:3.2.0'

一般使用Retrofit还会使用它和RxJava配套使用,因此还需要添加如下依赖

compile 'io.reactivex:rxjava:1.1.3'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'

为了使用更多的java注解添加下面的依赖

provided 'org.glassfish:javax.annotation:10.0-b28'

二、定义网络业务接口

Retrofit的网络请求都是写在一个接口中,并使用一定的注释如下面一组请求接口:注意接口中的每个方法的参数都需要使用标注,不采用标注将会报错。

public interface MyApiEndpointInterface {
    @GET("users/{username}") //note1
    Call<user> getUser(@Path("username") String username,@Header("Cache-Control") int maxAge);
 
    @Headers({"Cache-Control: max-age=640000", "User-Agent: My-App-Name"})//note2
    @POST("users/new")
    Call<user> createUser(@Body User user,@Query("sort") String sort);  //user支持被gson序列化的一个类,如JavaBean
 
    @FormUrlEncoded
    @POST("some/endpoint")
    Call<someresponse> someEndpoint(@FieldMap Map<string, string=""> names);
 
    @POST("https://blog.csdn.net/") //note3
    Call<response<user>> getUser(@Query("name") String name);
 
    @Multipart  //note4
    @POST("some/endpoint")
    Call<response> uploadImage(@Part("description") String description, @Part("image") RequestBody image)
 
    @GET("users/{username}") //note5
    void getUser(@Path("username") String username, Callback<user> cb);
}

1、Retrofit的网络请求返回的结果都是call的形式,?代表希望对Response body解析得到的数据类型;如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call

2、Retrofit的注解有如下几种常见注解

@GET 发送get方法的请求,@POST发送post方法的请求,@Header 网络请求的Header部分的键值对

@Body Post请求报文的Body内容,内容往往是一个对Java Bean解析后得到的JSON String,@Path网络路径的缺省值,@Query网络请求地址后面的查询键值对,如www.baidu.com/s?wd=REST&rsv_spt=1.

@FormUrlEncoded 和 @FieldMap配套使用,用于向Post表单传入键值对

3、一旦创建一个Retrofit实例就意味着网络请求根目录已经确定,但是Retrofit支持动态改变网络请求根目录。

4、使用@Multipart 标注的网络请求,用于上传文件;同时该请求必须在请求方法的参数中有一个使用@Part注解的参数。下面给出一个简单的使用例子

MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
file = new File("/storage/emulated/0/Pictures/MyApp/test.png");
RequestBody requestBody = RequestBody.create(MEDIA_TYPE_PNG, file);
Call<response> call = apiService.uploadImage("test", requestBody);

5、用于发送一个异步请求,不过在Retrofit2中已经没有这个了,异步请求和同步请求已经被合并。即通过Call的execute和queue方法分别发送同步和异步请求

三、得到网络业务接口的实体

public static final String BASE_URL = "http://api.myservice.com/";
Retrofit retrofit = new Retrofit.Builder() //note1
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create()) //gson负责对Response数据进行解析
    .build();
MyApiEndpointInterface apiService =  retrofit.create(MyApiEndpointInterface.class); //note2

1、获得一个Retrofit对象

2、由retrofit得到一个网络请求接口的实现类

四、使用接口实体获取Response

Call<user> call = apiService.getUser("evan",5000);
同步请求:
Response<user> response = call.execute();
异步请求:
call.enqueue(new Callback<user>() {
    @Override
    public void onResponse(Call<user> call, Response<user> response) {
       ....
    }
});

call只能使用一次,调用第二次的时候,就会出现失败的错误。当你想要多次请求一个接口的时候,直接用 clone 的方法来生产一个新的,相同的可用对象,clone代价很低。

Retrofit2 中 Response 对象增加了曾经一直被我们忽略掉的重要元数据:响应码(the reponse code),响应消息(the response message),以及读取相应头(headers){cookies}。

五、关于授权

//note1
Interceptor interceptor = new Interceptor() {
  @Override
  public okhttp3.Response intercept(Chain chain) throws IOException {
    Request newRequest = chain.request().newBuilder().addHeader("User-Agent", "Retrofit-Sample-App").build();
    return chain.proceed(newRequest);
  }
};
//note2
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(interceptor);
builder.cache(new Cache(new File("C:\\okhttp"),10*1024*1024)) ;
OkHttpClient client = builder.build();
//note3
Retrofit retrofit = new Retrofit.Builder()
  .baseUrl("https://api.github.com")
  .addConverterFactory(GsonConverterFactory.create())
  .client(client)
  .build();

1、创建拦截器,拦截器的工作就是在发送请求前在请求报文的header中添加一些键值对

2、添加前面的拦截器到client中,为了提高网络访问效率我们还为OkHttp设置了缓存,到此为止跟okhttp的操作都是一样的

3、为Retrofit设置个性化OkHttpClient对象

六、Retrofit和RxJava的配套使用

PartA 定义网络业务接口

public interface MyApiEndpointInterface {
    @GET("/users/{username}")
    Observable<user> getUser(@Path("username") String username);
 
    @POST("/users/new")
    Observable<user> createUser(@Body User user);
}

网络请求方法的返回值由之前的call转变成Observable, ?类支持使用gson对其进行序列化

PartB 得到网络业务接口的实体

RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.create(); //note1
RxJavaCallAdapterFactory rxAdapter = RxJavaCallAdapterFactory.createWithScheduler(Schedulers.io()); //note2
Retrofit retrofit = new Retrofit.Builder()
                               .baseUrl("https://api.github.com")
                               .addConverterFactory(GsonConverterFactory.create());
                               .addCallAdapterFactory(rxAdapter)
                               .build();
MyApiEndpointInterface apiService =  retrofit.create(MyApiEndpointInterface.class); //note3

1、默认发送同步的网络请求

2、默认发送异步的网络请求

3、获取网络请求实体

PartC使用示例

String username = "sarahjean";
Observable<user> call = apiService.getUser(username); //note1
Subscription subscription = call //note2
.subscribeOn(Schedulers.io()) 
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<user>() {
  @Override
  public void onCompleted() {
  }
  @Override
  public void onError(Throwable e) {
    if (e instanceof HttpException) {
       HttpException response = (HttpException)e;
       int code = response.code();
    }
  }
  @Override
  public void onNext(User user) {
  }
});

1、获取到Observable之后的使用与RxJava一样的使用流程

2、这里要十分注意的是在Android的Activity和Fragment中使用Rxjava需要在对应的onDestroy方法中调用subscription.unsubscribe()方法,防止OOM


  • Jerryasype的头像
    Jerryasype

    Классные строительные порталы здесь nfmuh.ru
    Классные строительные порталы здесь vipvozduh.ru
    Классные строительные порталы здесь vash-deputat.ru
    Классные строительные порталы здесь 495realty.ru

    2017-10-09 03:43


  • Ralphzem的头像
    Ralphzem

    Отличные строительные советы здесь akvakraska.ru
    Отличные строительные советы здесь ctoday.ru
    Отличные строительные советы здесь sportdon.ru
    Отличные строительные советы здесь wtsolutions.ru
    Отличные строительные советы здесь 1st-digital.ru
    Отличные строительные советы здесь yoga-altay.ru
    Отличные строительные советы здесь rebenokboleet.ru

    2017-10-17 07:03