Retrofit2.0初探

随着Google对OKHTTP的强势推动,和Volley的逐渐没落,而Retrofit也对okHttp进行了强制依赖。
Retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端,Retrofit其实质上就是对okHttp的封装,使用面向接口的方式进行网络请求,利用动态生成的代理类封装了网络接口请求的底层,
其将请求返回javaBean,对网络认证 REST API进行了很好的支持,使用Retrofit将会极大的提高我们应用的网络体验.
REST(REpresentational State Transfer)是一组架构约束条件和原则。
RESTful架构都满足以下规则:
(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”
依赖方式: compile 'com.squareup.retrofit2:retrofit:2.2.0’最新的版本号为2.2.0
Retrofit还提供以下几种Converter(转换器):

Gson: com.squareup.retrofit2:converter-gson 
Jackson: com.squareup.retrofit2:converter-jackson 
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives,boxed,andString): com.squareup.retrofit2:converter-scalars

后边介绍这几种转换器。。。
Retrofit会默认提供一个OKHttpClient实现 也可以关联okhttp3创建一个okhttpclient客户端
在使用Retrofit前,我们需要先创建Retrofit实例,并且做一系列配置,然而Retrofit设计的也是非常好,这些配置都是可插拔的:

Retrofit retrofit = new Retrofit.Builder()
//设置baseUrl,注意baseUrl 应该以/ 结尾。
.baseUrl("http://news-at.zhihu.com/api/4/")
//使用Gson解析器,可以替换其他的解析器
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
.client(new OkHttpClient())
//.client(new UrlConnectionClient())
//.client(new ApacheClient())
//.client(new CustomClient())
.build();

Retrofit 背后的 HTTP client,以及序列化机制(JSON/XML 协议)等都是可以替换,因此你可以选择自己合适的方案。Retrofit 最早出来的时候,只支持 Apache 的 HTTP client。后来增加了 URL connection,以及 OkHttp 的支持。如果你想使用其他的 HTTP client,可以通过以下方式了替换,或者更改为自定义的HTTP client:

//设置OKHttpClient,如果不设置会提供一个默认的
.client(new OkHttpClient())
//.client(new UrlConnectionClient())
//.client(new ApacheClient())
//.client(new CustomClient())

序列化功能也是可替换的。默认是用的 GSON,你当然也可以用 Jackson 来替换掉。转换器Converter上边都有写了,可以添加多种序列化Factory,但是GsonConverterFactory必须放在最后,否则会抛出异常(非常重要)。

//使用Gson解析器,可以替换其他的解析器
 .addConverterFactory(GsonConverterFactory.create())
 //当需要返回原始String数据时
 .addConverterFactory(ScalarsConverterFactory.create())

.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
addCallAdapterFactory提供RxJava支持,如果没有提供响应的支持(RxJava,Call),则会跑出异常。
2.0使用介绍
注意:retrofit2.0后:BaseUrl要以/结尾;@GET 等请求不要以/开头;@Url: 可以定义完整url,不要以 / 开头。
关于URL拼接注意事项:Retrofit 2.0:有史以来最大的改进
Retrofit注解:
方法注解:
包含@GET、@POST、@PUT、@DELETE、@PATH、@HEAD、@OPTIONS、@HTTP。
标记注解:
包含@FormUrlEncoded、@Multipart、@Streaming。
参数注解:
包含@Query,@QueryMap、@Body、@Field,@FieldMap、@Part,@PartMap。
其他注解:
@Path、@Header,@Headers、@Url
Retrofit通过注解实现了参数绑定 类型绑定 使用注解表明了请求将如何处理

1./**@HTTP:可以替代其他方法的任意一种
   * method 表示请的方法,不区分大小写
   * path表示路径
   * hasBody表示是否有请求体
   */
   @HTTP(method = "get", path = "users/{user}", hasBody = false)
   Call<ResponseBody> getFirstBlog(@Path("user") String user);

 2./**对baseurl进行替换拼接什么的
    * @Url:使用全路径复写baseUrl,适用于非统一baseUrl的场景。
    * 值得注意的是@Url需要在所有参数之前:
    */
    @GET
    Call<ResponseBody> v3(@Url String url);

3./***
   *@Streaming 用于下载大文件
   *文件下载我们需要使用@Url和 @Streaming ,@Url动态Url正好非常适合我们的场景,
   *而使用@Streaming注解可以让我们下载非常大的文件时,避免Retrofit将整个文件读进内存,
   *否则可能造成OOM现象。
   */
    @Streaming
    @GET("news/latest")
    Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl);

4.  /***
     *@Header 请求头参数
     *用于在方法参数里动态添加请求头:
     * 动态设置Header值
     */
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
    
//静态设置Header值
@Headers("Authorization: authorization")//这里authorization就是上面方法里传进来变量的值
@GET("widget/list")

5./***
   *@Headers 用于修饰方法,用于设置多个Header值:
   */
    @Headers({
            "Accept: application/vnd.github.v3.full+json",
            "User-Agent: Retrofit-Sample-App"
    })
    @GET("users/{username}")
    Call<UserBean> getUser(@Path("username") String username);
6./**
   *@Path:URL占位符,用于替换和动态更新,相应的参数必须使用相同的字符串被@Path进行注  
   *释
   */
    @GET("group/{id}/users")
    Call<List<UserBean>> groupList(@Path("id") int groupId);
    //--> http://baseurl/group/groupId/users
    //等同于:
    @GET
    Call<List<UserBean>> groupListUrl(@Url String url);
7. /**
    *@Query,@QueryMap:查询参数,用于GET查询,
    *需要注意的是@QueryMap可以约定是否需要encode
    */
@GET("group/users")
Call<List<UserBean>> groupList2(@Query("id") int groupId);
//--> http://baseurl/group/users?id=groupId
//或者
@GET("group/users")
Call<List<UserBean>> getNews(@QueryMap(encoded=true) Map<String, String> options);
8. /**
    * 用于Body的JSON格式参数
    *@Body:用于POST请求体,将实例对象根据转换方式转换为对应的json字符串参数,
    *这个转化方式是GsonConverterFactory定义的。
    * 配合@Headers("Accept-Encoding: application/json")使用
    */
    @POST("test/sayHi")
    @Headers("Accept-Encoding: application/json")
    Call<List<UserBean>> addUser(@Body UserBean user);
9./**服务器接受表单参数类型(form-data)时使用
   *@Field,@FieldMap:Post方式传递简单的键值对,
   *需要添加@FormUrlEncoded表示表单提交
   *Content-Type:application/x-www-form-urlencoded
   */
@FormUrlEncoded
@POST("test/sayHello")
Call<ResultBean> postSayHelloByForm(@Field("username") String username, @Field("age") String age);

10. /**
     *@Part,@PartMap:用于POST文件上传
     *其中@Part MultipartBody.Part代表文件,@Part(“key”) RequestBody代表参数
     *需要添加@Multipart表示支持文件上传的表单,Content-Type: multipart/form-data
     */
@Multipart
@POST("upload")
Call<ResponseBody> upload(@Part("description") RequestBody description, @Part MultipartBody.Part file);

搞了这么多我都不知道自己写了些什么
进入正题吧 Retrofit如何使用
大体分为三步吧
1:创建Retrofit实例

Retrofit retrofit = new Retrofit.Builder()
//设置baseUrl,注意baseUrl 应该以/ 结尾。
.baseUrl("http://news-at.zhihu.com/api/4/")//瞎比写得地址
//使用Gson解析器,可以替换其他的解析器
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
.client(new OkHttpClient())
//.client(new UrlConnectionClient())
//.client(new ApacheClient())
// .client(new CustomClient())
.build();

2:创建接口

public interface PubService {
    /**@HTTP:可以替代其他方法的任意一种
     * method 表示请的方法,不区分大小写
     * path表示路径
     * hasBody表示是否有请求体
     */
    @HTTP(method = "get", path = "users/{user}", hasBody = false)
    Call<ResponseBody> getFirstBlog(@Path("user") String user);

    /**对baseurl进行替换拼接什么的
     * @Url:使用全路径复写baseUrl,适用于非统一baseUrl的场景。
     */
    @GET
    Call<ResponseBody> v3(@Url String url);

    /***
     *@Streaming 用于下载大文件
     *文件下载我们需要使用@Url和 @Streaming ,@Url动态Url正好非常适合我们的场景,
     *而使用@Streaming注解可以让我们下载非常大的文件时,避免Retrofit将整个文件读进内存,
     *否则可能造成OOM现象。
     */
    @Streaming
    @GET
    Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl);
    /***
     *@Header 请求头参数
     *用于在方法参数里动态添加请求头:
     * 动态设置Header值
     */
    @GET("news/latest")
    Call<ResultBean> postSayHi(@Header("city") String city);

    /***
     *@Headers 用于修饰方法,用于设置多个Header值:
     */
    @Headers({
            "Accept: application/vnd.github.v3.full+json",
            "User-Agent: Retrofit-Sample-App"
    })
    @GET("users/{username}")
    Call<UserBean> getUser(@Path("username") String username);

    /**
     * @Path:URL占位符,用于替换和动态更新,相应的参数必须使用相同的字符串被@Path进行注释
     */
    @GET("group/{id}/users")
    Call<List<UserBean>> groupList(@Path("id") int groupId);
    //--> http://baseurl/group/groupId/users
    //等同于:
    @GET
    Call<List<UserBean>> groupListUrl(@Url String url);

    /**
     *@Query,@QueryMap:查询参数,用于GET查询,需要注意的是@QueryMap可以约定是否需要encode
     */
    @GET("group/users")
    Call<List<UserBean>> groupList2(@Query("id") int groupId);
    //--> http://baseurl/group/users?id=groupId
    //或者
    @GET("group/users")
    Call<List<UserBean>> getNews(@QueryMap(encoded=true) Map<String, String> options);

    /**
     * 用于Body的JSON格式参数
     *@Body:用于POST请求体,将实例对象根据转换方式转换为对应的json字符串参数,
     *这个转化方式是GsonConverterFactory定义的。
     * 配合@Headers("Accept-Encoding: application/json")使用
     */
    @POST("test/sayHi")
    @Headers("Accept-Encoding: application/json")
    Call<List<UserBean>> addUser(@Body UserBean user);

    /**服务器接受表单参数类型(form-data)时使用
     *@Field,@FieldMap:Post方式传递简单的键值对,
     *需要添加@FormUrlEncoded表示表单提交
     *Content-Type:application/x-www-form-urlencoded
     */
    @FormUrlEncoded
    @POST("test/sayHello")
    Call<ResultBean> postSayHelloByForm(@Field("username") String username, @Field("age") String age);


    /**
     *@Part,@PartMap:用于POST文件上传
     *其中@Part MultipartBody.Part代表文件,@Part(“key”) RequestBody代表参数
     *需要添加@Multipart表示支持文件上传的表单,Content-Type: multipart/form-data
     */
    @Multipart
    @POST("upload")
    Call<ResponseBody> upload(@Part("description") RequestBody description, @Part MultipartBody.Part file);

3:异步回调

Retrofit retrofit = new Retrofit.Builder()
                     .baseUrl("http://gc.ditu.aliyun.com/")
                     .addConverterFactory(GsonConverterFactory.create())
                     .build();
QuestService service = retrofit.create(QuestService.class);
final Call<LoginInfo> loginInfo = service.loadInfo();
loginInfo.enqueue(new Callback<LoginInfo>() {
    @Override
    public void onResponse(Call<LoginInfo> call, Response<LoginInfo>   response){
            LoginInfo info = respnse.body();
         }

    @Override
    public void onFailure(Call<LoginInfo> call, Throwable t) {
    
    }
});

4.取消请求

loginInfo.cancel();
 //Call<StartImageBean> cloneRequsest = startImage.clone();//复制
定义的接口
public interface PService {
@GET("start-image/1080*1776")
Call<StartImageBean> getStartImage();

@GET("start-image/{size}")
Call<StartImageBean> getStartImageByPath(@Path("size") String size);
/**
 * sayHello 动态get 参数
 *
 * @param username
 * @param age
 * @return
 */
@GET("test/sayHello")
Call<String> sayHello(@Query("username") String username, @Query("age") String age);
@POST
Call<ResultBean> postSayHelloByURL(@Url String url, @Query("username") String username, @Query("age") String age);
@POST("test/sayHi")
@Headers("Accept-Encoding: application/json")
    //使用@Headers 可添加header
Call<ResultBean> postSayHi(@Body UserBean userBean);
@Multipart
@POST("test/upload")
Call<ResultBean> upload(@Part("file\"; filename=\"launcher_icon.png") RequestBody file);

//http://localhost:8080/app/res/atom-amd64.deb
@Streaming
@GET
Call<ResponseBody> downloadFileByDynamicUrlAsync(@Url String downloadUrl);
}

//简单使用方法:
1.普通 GET 返回实体对象

private void getStartImage() {
   //生成Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
//设置baseUrl,注意baseUrl 应该以/ 结尾。
.baseUrl("http://xxx.com/api/xx/")
//使用Gson解析器,可以替换其他的解析器
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
.client(new OkHttpClient())
.build();     

PService messageService = retrofit.create(PService.class);
Call<StartImageBean> startImage = messageService.getStartImage();
startImage.enqueue(new Callback<StartImageBean>() {
        @Override
  public void onResponse(Call<StartImageBean> call, 
  Response<StartImageBean> response) {
            if (response.isSuccessful()) {
                Log.d(TAG, response.body().toString());
                resultTextView.setText("" + response.body().toString());
            }
        }
        @Override
        public void onFailure(Call<StartImageBean> call, Throwable t) {
            resultTextView.setText("" + "error:" + t.getMessage());
        }
    });
 }

2.动态URL GET 返回实体对象

private void getStartImageByPath() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://news-at.zhihu.com/api/4/")
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
.build();

PService messageService = retrofit.create(PService.class);
 /**
  * 可使用以下格式做动态URL参数
  * 320*432
  480*728
  720*1184
  1080*1776
  */
Call<StartImageBean>startImage=messageService.getStartImageByPath("320*432");
 //异步请求
startImage.enqueue(new Callback<StartImageBean>() {
       @Override
public void onResponse(Call<StartImageBean> call, Response<StartImageBean> response) {
           if (response.isSuccessful()) {
               Log.d(TAG, response.body().toString());
               resultTextView.setText("" + response.body().toString());
           }
       }
       @Override
       public void onFailure(Call<StartImageBean> call, Throwable t) {
           resultTextView.setText("" + "error:" + t.getMessage());
       }
   });
}

3.GET 动态参数 返回String 返回String类型的json串

private void getSayHello() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
//在build.gradle添加
// compile 'com.squareup.retrofit2:converter-scalars:2.1.0+'
.addConverterFactory(ScalarsConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
.build();
PService myTestApiService = retrofit.create(PService.class);
Call<String> doubanCall = myTestApiService.sayHello("fuchenxuan", "110");
doubanCall.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                if (response.isSuccessful()) {
                    Log.d(TAG, response.body().toString());
                    resultTextView.setText("" + response.body().toString());
                }
            }
            @Override
            public void onFailure(Call<String> call, Throwable t) {

            }
        });
    }

4.普通 POST 返回实体对象

private void postSayHello() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
.build();
PService myTestApiService = retrofit.create(PService.class);
//Call<ResultBean> doubanCall 
= myTestApiService.postSayHello("fuchenxuan", "110");
//Call<ResultBean> doubanCall 
= myTestApiService.postSayHelloByForm("fuchenxuan", "110");
//用到了Url注解
Call<ResultBean> doubanCall 
= myTestApiService.postSayHelloByURL(API_BASE_URL.concat("test/sayHello"), "fuchenxuan", "110");
doubanCall.enqueue(new Callback<ResultBean>() {
            @Override
        public void onResponse(Call<ResultBean> call, Response<ResultBean> response) {
                if (response.isSuccessful()) {
                    Log.d(TAG, response.body().toString());
                    resultTextView.setText("" + response.body().toString());
                }
            }
            @Override
            public void onFailure(Call<ResultBean> call, Throwable t) {

            }
        });
    }

5.POST JSON 参数

    private void postSayHi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
//检测接口定义是否正确,适合在开发、测试时使用
.validateEagerly(true)
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
//使用RxJava
//.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();

PService myTestApiService = retrofit.create(PService.class);
UserBean userBean = new UserBean("fuchenxuan", "1110");
Call<ResultBean> doubanCall = myTestApiService.postSayHi(userBean);
  doubanCall.enqueue(new Callback<ResultBean>() {
     @Override
   public void onResponse(Call<ResultBean> call, Response<ResultBean> response) {
                if (response.isSuccessful()) {
                    //返回原始数据格式
                    try {
                        Log.d(TAG, response.raw().body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    resultTextView.setText("" + response.body().toString());
                }

            }

            @Override
            public void onFailure(Call<ResultBean> call, Throwable t) {

            }
        });
    }

6.文件上传

private void upload() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
.build();

PService myTestApiService = retrofit.create(PService.class);
File file = new File(getExternalFilesDir(null), "launcher_icon.png");
RequestBody fileBody 
= RequestBody.create(MediaType.parse("image/png"), file);
Call<ResultBean> doubanCall = myTestApiService.upload(fileBody);
doubanCall.enqueue(new Callback<ResultBean>() {
            @Override
    public void onResponse(Call<ResultBean> call, Response<ResultBean> response) {
                if (response.isSuccessful()) {
                    Log.d(TAG, response.body().toString());
                    resultTextView.setText("" + response.body().toString());
                }
            }
            @Override
            public void onFailure(Call<ResultBean> call, Throwable t) {
//                Log.d(TAG, response.body().toString());
                resultTextView.setText("" + "error:" + t.getMessage());
            }
        });
    }

7.文件下载

private void downloadFileByDynamicUrlAsync() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
//设置OKHttpClient,如果不设置会提供一个默认的
//.client(new OkHttpClient())
.build();
final PService myTestApiService = retrofit.create(PService.class);
   new AsyncTask<Void, Long, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
             Call<ResponseBody> call    
                =myTestApiService.downloadFileByDynamicUrlAsync(API_BASE_URL.concat("/res/atom-amd64.deb"));
                try {
                    Response<ResponseBody> response = call.execute();
                    boolean writtenToDisk = writeResponseBodyToDisk(response.body());
                    Log.d(TAG, "下载文件 " + writtenToDisk);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }
        }.execute();
    }

8.自定义Converter

9.自定义拦截器Interceptor

10.全局单例的okhttpclient和retrofit
未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值