Retrofit详解

来源:互联网 发布:怎么注册淘宝账号 编辑:程序博客网 时间:2024/06/06 03:18

在目前的开发环境下,相信Retrofit这个词大家已经非常熟悉了,就像之前volley刚出来的时候大家都一起去使用volley,研究volley源码,进行再次封装使用到自己的项目中;那我也不例外,在之前封装过volley网络框架的基础下也来研究研究retrofit到底有什么比较独特的之处,不过大家要知道retrofit是对okhttp再做了一层封装,你只需要简单的进行一些配置就能顺利使用retrofit来进行网络请求了。

当研究一个框架的时候建议大家从官网和源码下手,虽然目前已经有了很多的文章讲解如何使用Retrofit以及它的源码分析,但是毕竟只有经历过自己研究后总结写出来的东西才属于自己真正的知识,也方便以后去复习和回顾。

Retrofit参考地址:
Retrofit官网介绍
Github源代码下载和示例代码
本文中涉及到的demo代码都在Github上:
Demo

1.Retrofit的基本使用

从官网可以看到,Retrofit给我们示例了如何简单的请求网络以及得到结果对象;那么我也利用github提供的api接口来写了一个小demo来给大家演示如何快速使用Retrofit进行网络请求。下面给大家看一个一般的get请求网络方式。

1)首先定义一个接口对象

public interface GitHubService {    @GET("users/{user}")    Call<User> getUser(@Path("user") String user);}

GitHubService接口中有一个getUser的方法,接收一个String类型的参数user用户名。该方法通过注解标明为Get请求方式。

User对象就是一个javaBean对象,里面有一些用户的参数信息,由于字段较多就不在这贴出,具体可以参考示例demo

2)通过Retrofit得到GitHubService对象

Retrofit retrofit = new Retrofit.Builder().                baseUrl("https://api.github.com/").                addConverterFactory(GsonConverterFactory.create()).                build();        GitHubService service = retrofit.create(GitHubService.class);        final Call<User> mTestUser = service.getUser("zphuanlove");

这里指定了基本的url,配合着GET注解中的value值形成一个完整的请求路径。

注意上诉代码是在MainActivity主线程中执行

3)同步请求
由于是在主线程中请求网络,同步请求的方式需要new一个子线程来请求:

new Thread(new Runnable() {    @Override    public void run() {        try {            //同步的方式            Response<User> response = mTestUser.execute();            User user = response.body();            Log.i("zph","user:"+user.toString());        } catch (IOException e) {            e.printStackTrace();        }    }}).start();

4)异步的请求

//异步的方式mTestUser.enqueue(new Callback<User>() {    @Override    public void onResponse(Call<User> call, Response<User> response) {        User body = response.body();        Log.i("zph","body:"+body.toString());    }    @Override    public void onFailure(Call<User> call, Throwable t) {        Log.e("zph","error:"+t.toString());    }});

通过上诉的代码我们就可以快速的完成一个GET方式的请求,而且Retrofit的源码中提供了有22种注解的方式来供我们请求网络以及配置请求方式.

2.注解的使用和分析
1)Http请求方式

在Retrofit请求Http的方式中一共提供了GET,POST,PUT,PATCH,DELETE,HEAD这几种标准的HTTP请求方法,我们可以看看GET和POST注解的源码:

*GET

/** Make a GET request. */@Documented@Target(METHOD)@Retention(RUNTIME)public @interface GET {  /**   * A relative or absolute path, or full URL of the endpoint. This value is optional if the first   * parameter of the method is annotated with {@link Url @Url}.   * <p>   * See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how   * this is resolved against a base URL to create the full endpoint URL.   */  String value() default "";}

*POST

/** Make a POST request. */@Documented@Target(METHOD)@Retention(RUNTIME)public @interface POST {  /**   * A relative or absolute path, or full URL of the endpoint. This value is optional if the first   * parameter of the method is annotated with {@link Url @Url}.   * <p>   * See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how   * this is resolved against a base URL to create the full endpoint URL.   */  String value() default "";}

其他几个注解也都是类似,可以看到这些注解都是作用于方法上,并且是在运行期有效,JVM在运行期通过反射获得注解信息,也就是定义的时候的value值(默认是“”),一般用于动态设置具体的接口请求path,配合BaseUrl组成一个完整的Url,所以如何动态传递path,Retrofit也给我们提供了一个注解Path,看看他的源码:

*PATH

@Documented@Retention(RUNTIME)@Target(PARAMETER)public @interface Path {  String value();  /**   * Specifies whether the argument value to the annotated method parameter is already URL encoded.   */  boolean encoded() default false;}

运行时有效,并且作用于参数上,结合着我们上面的Retrofit基本使用大家应该就明白了这个示例代码的原理了。

不过除了使用上诉的基本HTTP请求方式以外,Retrofit还给我们提供了一种HTTP注解的方式可以自己配置请求方式和path,可以看到下面的代码我使用了HTTP注解的方式同样也可以达到GET请求方式的效果:

public interface GitHubService {    @GET("users/{user}")    Call<User> getUser(@Path("user") String user);    @HTTP(method = "GET",path = "users/{user}",hasBody = false)    Call<User> getUser4Http(@Path("user") String user);}

注意这里的method值尽量用大写,如果是post请求hasBody改为true。

*HTTP

@Documented@Target(METHOD)@Retention(RUNTIME)public @interface HTTP {  String method();  /**   * A relative or absolute path, or full URL of the endpoint. This value is optional if the first   * parameter of the method is annotated with {@link Url @Url}.   * <p>   * See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how   * this is resolved against a base URL to create the full endpoint URL.   */  String path() default "";  boolean hasBody() default false;}

2)请求参数的不同配置

我们都知道在请求的过程中我们是可以携带请求参数给服务器的,Get请求是直接拼接在Url后面,而post请求是放在body中;下面我们就开始介绍下Query,QueryMap,Body,Filed,Part,Head一些注解的使用说明。

  • Query和QueyMap

    Query和QueyMap是作用于请求Url上的参数表现形式,比如我们要请求一个GitHub上的某一个用户的关注用户,具体URl路径是:

http://baseurl/users/{user}/following?sort=id

那么就可以通过PATH和QUERY注解的方式来表达,具体代码如下,定义请求方法:

/** * 得到某个用户在github上关注的用户 * @param user:用户名 * @param sort:参数sort  需要在调用的时候赋值 * @return */@GET("users/{user}/following")Call<List<User>> getUserFollowings(@Path("user") String user, @Query("sort")

具体请求代码如下:

@Testpublic void testFollowing() throws Exception{    Retrofit retrofit = new Retrofit.Builder().            baseUrl(GitHubService.BASE_URL).            addConverterFactory(GsonConverterFactory.create()).            build();    GitHubService service = retrofit.create(GitHubService.class);    Call<List<User>> userFollowings = service.getUserFollowings("zphuanlove", "id");    Response<List<User>> response = userFollowings.execute();    List<User> users = response.body();    System.out.println("users:"+users.toString());}

同样的如果请求需要带多个参数,那么可以使用QueryMap,比如:

/** * 得到某个公司下得所有用户 * @return */@GET("group/{id}/users")Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
  • Body
    Body的使用主要用于POST请求,携带参数,使用跟一般请求网络框架没什么差别,比如我想在GitHub上创建一个用户,那么需要携带一个User对象过去,这时使用Post提交就非常方便了:
/** * 在GitHub上创建用户 * @param user * @return */@POST("users/new")Call<User> createUser(@Body User user);

具体请求代码:

@Testpublic void testCreatUser() throws Exception{    Retrofit retrofit = new Retrofit.Builder().            baseUrl(GitHubService.BASE_URL).            addConverterFactory(GsonConverterFactory.create()).            build();    GitHubService service = retrofit.create(GitHubService.class);    //由于user字段太多就不演示,直接new一个空对象    Call<User> user = service.createUser(new User());    //返回也是一个空对象    User body = user.execute().body();    System.out.println("user:"+body);}
原创粉丝点击