Retrofit框架

一、概述:

Retrofit框架是Square公司出品的网络加载框架,是在OkHttp框架作为底层的基础上进行改良,运行效率高,实现起来更加简单。目前Retrofit的最新版本是2.0。

特点
  • 性能好、处理快、使用简单。Retrofit 是目前安卓最流行的HTTP Client库之一;
  • 使用REST API时非常方便;
  • 支持NIO;
  • 速度上比volley更快;
  • Retrofit默认会使用OKHttp处理网络层请求;
  • 默认使用Gson解析


二、Retrofit的使用步骤(支持同步请求和异步请求)
(一)、导入依赖包

1、gradle导包:

如果只想导入Retrofit 2.0,那么在build.gradle的依赖里面添加代码:

1  compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4’

Sync gradle 文件之后你就可以使用Retrofit 2.0了。

会观察到External Libraries中增加了:

  • retrofit-2.0.0-beta4
  • okhttp-3.0.1
  • okie-1.6.0

如果添加以下代码:

2  compile 'com.squareup.retrofit2:converter-goon:2.0.0-beta4’

那么同步后,External Libraries中会增加:

  • retrofit-2.0.0-beta4
  • okhttp-3.0.1
  • okie-1.6.0
  • gson-2.4
  • converter-gson-2.0.0-beta4

以上这几个依赖包都是Sqareup团队开发的。


(二)、代码实现步骤

1、定义一个接口(接口的作用是封装URL地址和数据的请求)
关于接口中URL的定义方式将在下一节中具体讲解。

示例代码:

1
2
3
4
5
6
7
8

public interface ServiceInterface {

//Get请求
@GET("/相对路径")//如"/Demo/{text}/index.jsp?" 
Call<T> getT(@Path("text") String text,@Query("page") int page);

【备注】:这里的"{"  和  "}" 所括起来的部分是我们要替换的参数,替换的方式就是在getT这个方法中声明一个注解@Path("text"),里面的参数一定要去括号里的参数对应。 用@Query标注的参数是页数 ,对应的相对地址为"/Demo/{text}/index.jsp?page=1"

@FormMutiled
@POST("/相对路径")//如"/Demo/{text}/index?" 
Call<T> postT(@Path("text") String text, @Field("key1") String value1, @Field("key2") String value2 );

【备注:】postT的方法传入参数,有几个参数就传入几个参数,传入的方式为 @Field("key") String value。的形式,如果是可变参数的应用FieldMap Map<String,String> map,就可以。
}


2、实例化Retrofit


 
 
1
2
3

Retrofit retrofit=new Retrofit.Builder()
  .baseUrl(" http://www.baidu.com ")
  .convert(GsonConvertFactory.create())
 .build();



3、通过Retrofit实例创建接口服务对象
ServiceInterface  serviceInterface = retrofit.create(QsService.class);

4、接口服务对象调用接口中方法,返回网络请求Call对象
Call<T> call = serviceInterface.getT(传入相应的参数);

5、Call对象执行请求

如果要调用同步请求,只需调用execute(),或者调用enqueue()来发起一个异步请求。

A、异步执行请求
call.enqueue(new Callback(){
public void success(Response<T> response){
T t = response.body();
}
public void failure(String msg,Exception exception){};
});

以上代码发起了一个在后台线程的请求并从response 的response.body()方法中获取一个结果对象。注意这里的onResponse和onFailure方法是在主线程中调用的。建议你使用enqueue,它最符合 Android OS的习惯。


B、同步执行请求

Response<T> response = call.execute();


以上的代码会阻塞线程,因此你不能在安卓的主线程中调用,不然会面临NetworkOnMainThreadException。如果你想调用execute方法,请在后台线程执行。

【备注:】T的泛型种类 可以是:数据模型类数据实体类,或者ResponseBody


6、取消正在进行中的业务

service 的模式变成Call的形式的原因是为了让正在进行的事务可以被取消。要做到这点,你只需调用call.cancel()。

1  call.cancel();

事务将会在之后立即被取消。

7、Gson解析  在Retrofit 2.0中,Converter 不再包含在package 中了。你需要自己插入一个Converter 不然的话Retrofit 只能接收字符串结果。同样的,Retrofit 2.0也不再依赖于Gson 。

如果你想接收json 结果并解析成DAO,你必须把Gson Converter 作为一个独立的依赖添加进来。

1 compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'


1 Retrofit retrofit = new Retrofit.Builder()
2         .baseUrl("http://api.nuuneoi.com/base/")
3         .addConverterFactory(GsonConverterFactory.create())
4         .build();
5   
6 service = retrofit.create(APIService.class);

这里是Square提供的官方Converter modules列表。选择一个最满足你需求的。

Gson: com.squareup.retrofit:converter-gson

Jackson: com.squareup.retrofit:converter-jackson

Moshi: com.squareup.retrofit:converter-moshi

Protobuf: com.squareup.retrofit:converter-protobuf

Wire: com.squareup.retrofit:converter-wire

Simple XML: com.squareup.retrofit:converter-simplexml

也可以通过实现Converter.Factory接口来创建一个自定义的converter 。

我比较赞同这种新的模式。它让Retrofit对自己要做的事情看起来更清晰。

8、自定义Gson对象

为了以防你需要调整json里面的一些格式,比如,Date Format。你可以创建一个Gson 对象并把它传递给GsonConverterFactory.create()。

01 Gson gson = new GsonBuilder()
02         .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
03         .create();
04   
05 Retrofit retrofit = new Retrofit.Builder()
06         .baseUrl("http://api.nuuneoi.com/base/")
07         .addConverterFactory(GsonConverterFactory.create(gson))
08         .build();
09   
10 service = retrofit.create(APIService.class);

三、Retrofit2.0中接口服务类的写法

(一)、注解种类

1、@GET
GET网络请求方式
2、@POST
POST网络请求方式
3、@Headers
头信息参数
4、@Path
路径参数。替换url地址中 "{"  和  "}" 所括起来的部分。
5、@Query
GET请求时查询参数。将在url地址中追加类似 “page=1”的字符串,形成提交给服务器端的请求参数。
6、@QueryMap
查询参数集合。 在url地址中追加类似 “type=text&count=30&page=1”的字符串,形成提交给服务器端的请求参数。
7、@FormUrlEncoded
可以对表单域中填写的内容进行编码处理,避免客户端与服务器端字符集不统一, 参数在传递到服务器后 出现乱码。
8、@Multipart
post提交分块请求。如果上传文件,必须指定Multipart。
9、@Field
指定form表单域中每个控件的name及相应数值。
10、@FieldMap
表单域集合
11、@Part
POST提交分块请求

(二)、URL的定义方式

Retrofit 2.0使用了新的URL定义方式。Base URL与@Url 不是简单的组合在一起而是和<a href="...">的处理方式一致。用下面的几个例子阐明。

Android上最流行的HTTP Client库,Retrofit 2.0:有史以来最大的改进

Android上最流行的HTTP Client库,Retrofit 2.0:有史以来最大的改进

Android上最流行的HTTP Client库,Retrofit 2.0:有史以来最大的改进

ps:貌似第二个才符合习惯。

对于 Retrofit 2.0中新的URL定义方式,这里建议:

- Base URL: 总是以 /结尾

- @Url: 不要以 / 开头

比如

01 public interface APIService {
02   
03     @POST("user/list")
04     Call<Users> loadUsers();
05   
06 }
07   
08 public void doSomething() {
09     Retrofit retrofit = new Retrofit.Builder()
10             .baseUrl("http://api.nuuneoi.com/base/")
11             .addConverterFactory(GsonConverterFactory.create())
12             .build();
13   
14     APIService service = retrofit.create(APIService.class);
15 }

以上代码中的loadUsers会从 http://api.nuuneoi.com/base/user/list获取数据。

而且在Retrofit 2.0中还可以在@Url里面定义完整的URL

1 public interface APIService {
2   
4     Call<Users> loadSpecialUsers();
5   
6 }

这种情况下Base URL会被忽略

四、Retrofit与OkHttp

(一)、Retrofit2.0中默认包含OkHttp依赖包

OkHttp 在Retrofit 1.9里是可选的。如果你想让Retrofit 使用OkHttp 作为HTTP 连接接口,你需要手动包含okhttp 依赖。

但是在Retrofit 2.0中,OkHttp 是必须的,并且自动设置为了依赖,但是该OkHttp在okhttp3这个包下。为了让OkHttp 的Call模式成为可能,在Retrofit 2.0中OkHttp 自动被用作HTTP 接口。

实例化OkHttpClient对象,然后添加到Retrofit的Builder链中

1 OkHttpClient client = new OkHttpClient();
Retrofit retrofit = 
new Retrofit.Builder()
2         .baseUrl("http://api.nuuneoi.com/base/")
3         .addConverterFactory(GsonConverterFactory.create())
4         .client(client)
5         .build();

(二)、缺少INTERNET权限会导致SecurityException异常

在Retrofit 1.9中,如果你忘记在AndroidManifest.xml文件中添加INTERNET权限。异步请求会直接进入failure回调方法,得到PERMISSION DENIED 错误消息。没有任何异常被抛出。

但是在Retrofit 2.0中,当你调用call.enqueue或者call.execute,将立即抛出SecurityException,如果你不使用try-catch会导致崩溃。

Android上最流行的HTTP Client库,Retrofit 2.0:有史以来最大的改进

这类似于在手动调用HttpURLConnection时候的行为。当INTERNET权限添加到了 AndroidManifest.xml中就没有什么需要考虑的了。

(三)、使用 Interceptor

在Retrofit 1.9中,你可以使用RequestInterceptor来拦截一个请求,但是它已经从Retrofit 2.0 移除了,因为HTTP连接层已经转为OkHttp。

结果就是,现在我们必须转而实用OkHttp里面的Interceptor。

首先你需要实用Interceptor创建一个OkHttpClient对象,如下:

01 OkHttpClient client = new OkHttpClient();
02 client.interceptors().add(new Interceptor() {
03     @Override
04     public Response intercept(Chain chain) throws IOException {
05         Response response = chain.proceed(chain.request());
06   
07         // Do anything with response here
08   
09         return response;
10     }
11 });

然后传递创建的client到Retrofit的Builder链中。

1 Retrofit retrofit = new Retrofit.Builder()
2         .baseUrl("http://api.nuuneoi.com/base/")
3         .addConverterFactory(GsonConverterFactory.create())
4         .client(client)
5         .build();


五、RxJava Integration with CallAdapter

除了使用Call模式来定义接口,我们也可以定义自己的type,比如MyCall。。我们把Retrofit 2.0的这个机制称为CallAdapter。

Retrofit团队有已经准备好了的CallAdapter module。其中最著名的module可能是为RxJava准备的CallAdapter,它将作为Observable返回。要使用它,你的项目依赖中必须包含两个modules。

1 compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
2 compile 'io.reactivex:rxandroid:1.0.1'

Sync Gradle并在Retrofit Builder链表中如下调用addCallAdapterFactory:

1 Retrofit retrofit = new Retrofit.Builder()
2         .baseUrl("http://api.nuuneoi.com/base/")
3         .addConverterFactory(GsonConverterFactory.create())
4         .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
5         .build();

你的Service接口现在可以作为Observable返回了!

1 Retrofit retrofit = new Retrofit.Builder()
2         .baseUrl("http://api.nuuneoi.com/base/")
3         .addConverterFactory(GsonConverterFactory.create())
4         .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
5         .build();

你可以完全像RxJava那样使用它,如果你想让subscribe部分的代码在主线程被调用,需要把observeOn(AndroidSchedulers.mainThread())添加到链表中。

01 Observable<DessertItemCollectionDao> observable = service.loadDessertListRx();
02   
03 observable.observeOn(AndroidSchedulers.mainThread())
04     .subscribe(new Subscriber<DessertItemCollectionDao>() {
05         @Override
06         public void onCompleted() {
07             Toast.makeText(getApplicationContext(),
08                     "Completed",
09                     Toast.LENGTH_SHORT)
10                 .show();
11         }
12   
13         @Override
14         public void onError(Throwable e) {
15             Toast.makeText(getApplicationContext(),
16                     e.getMessage(),
17                     Toast.LENGTH_SHORT)
18                 .show();
19         }
20   
21         @Override
22         public void onNext(DessertItemCollectionDao dessertItemCollectionDao) {
23             Toast.makeText(getApplicationContext(),
24                     dessertItemCollectionDao.getData().get(0).getName(),
25                     Toast.LENGTH_SHORT)
26                 .show();
27         }
28     });



【备注:Retrofit的英文解释】

Retrofit is one of the most popular HTTP Client Library for Android as a result of its simplicity and its great performance compare to the others.

Anyway its weakness is there is no any straight way to cancel the ongoing transaction in Retrofit 1.x. If you want to do that you have to call it on Thread and kill it manually which is quite hard to manage.

Square gave a promise years ago that this feature will be available on Retrofit 2.0 but years passed, there is still no updated news on this.

Until last week, Retrofit 2.0 just passed its Release Candidate stage to Beta 1 and has been publicly launched to everyone. After giving it a try, I must say that I am quite impressed on its new pattern and its new features. There are a lot of changes in the good way. I will describe those in this article. Let's get started !

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值