您的位置:首页 > 理论基础 > 计算机网络

Retrofit2.0初识

2017-05-13 14:45 246 查看
其实关于 Retrofit2.0 网上的介绍已经很多了,这里我只是根据众多资料以及自己使用之后写点自己的想法,本篇文章参考以下链接:

1.  Retrofit 2.0非常简单的入门(翻译官方文档):http://www.jianshu.com/p/442a29da7b23

2. Retrofit 官网:http://square.github.io/retrofit/

3. Retrofit2.0使用总结:http://www.jianshu.com/p/3e13e5d34531

在此感谢!

下面对 Retrofit2.0做简单讲解:

首先,添加 网络链接权限
<uses-permission android:name="android.permission.INTERNET" />


app 的 build.gradle 中添加依赖包,由于解析过程中用到Gson,故也要添加 gson 依赖

   
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'


Retrofit2.0的使用分三步:

1.写url接口类

2.写Retrofit对象,并配置网络

3.编写调用网络通讯方法

OK,首先讲第一步,先命名一个接口类,用于放众多的url,类似如下:
public interface ApiService<T>{

//注册时获取短信验证码
@POST("api/login/pushSms")
@FormUrlEncoded
Call<ApiResponse<SmsCode>> postSms(@FieldMap Map<String, String> map);
}


下面对 Retrofit2.0 的注解做些解释,注解一般分为:

方法注解,包含@GET、@POST、@PUT、@DELETE、@PATH、@HEAD、@OPTIONS、@HTTP。

标记注解,包含@FormUrlEncoded、@Multipart、@Streaming。

参数注解,包含@Query,@QueryMap、@Body、@Field,@FieldMap、@Part,@PartMap。

其他注解,@Path、@Header,@Headers、@Url

下面做具体讲解:

@HTTP:可以替代其他方法的任意一种

/**
* method 表示请的方法,不区分大小写
* path表示路径
* hasBody表示是否有请求体
*/
@HTTP(method = "get", path = "users/{user}", hasBody = false)
Call<ResponseBody> getFirstBlog(@Path("user") String user);


//=============== URL操作 =================================

    //@Url:使用全路径复写baseUrl,适用于非统一baseUrl的场景。
@GET
Call<ResponseBody> getInfo(@Url String url);
   

    //当请求的url中含动态字符串参数时,用@Path表示请求参数
@GET("users/{user}/repos")
Call<List<T>> listRepos(@Path("user") String user);


    //你也可以将query参数直接写在URL里静态传输
@GET("users/list?sort=desc")
Call<String>getResponse();


    //Query参数也能同时添加
@GET("group/{id}/users")
Call<List<T>> groupList(@Path("id") int groupId, @Query("sort") String sort);


    //复杂的query参数可以用Map来构建
@GET("group/{id}/users")
Call<List<T>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);


//=============== 请求主体 =================================

    //能够通过@Body注解来指定一个方法作为HTTP请求主体,这个参数对象会被Retrofit实例中的converter进行转化。

    // 如果没有给Retrofit实例添加任何converter的话则只有RequestBody可以作为参数使用
@POST("users/new")
Call<User> createUser(@Body User user);


    //可以通过@FormUrlEncoded注解方法来发送form-encoded的数据。

    // 每个键值对需要用@Filed来注解键名,随后的对象需要提供值。(直接传key-value参数)
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);


    //也可以通过@Multipart注解方法来发送Mutipart请求。每个部分需要使用@Part来注解。

    //多个请求部分需要使用Retrofit的converter或者是自己实现 RequestBody来处理自己内部的数据序列化
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);


   //@Streaming:用于下载大文件
@Streaming
@GET
Call<ResponseBody> downloadFileWithDynamicUrlAsync(@Url String fileUrl);


//    @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);
// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java // use the FileUtils to get the actual file by uri
File file = FileUtils.getFile(this, fileUri);

// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);

// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("picture", file.getName(), requestFile);

// add another part within the multipart request
String descriptionString = "hello, this is description speaking";
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), descriptionString);


//=============== 请求头部 ======================= 

//你可以通过使用@Headers注解来设置请求静态头。 

@Headers("Cache-Control: max-age=640000")
@GET("widget/list") Call<List<User>> widgetList();

//注意的是头部参数并不会相互覆盖,同一个名称的所有头参数都会被包含进请求里面。 
@Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App" })
@GET("users/{username}") Call<User> getUser(@Path("username") String username);


//你可以通过 @Header 注解来动态更新请求头。一个相应的参数必须提供给 @Header 注解。 

// 如果这个值是空(null)的话,那么这个头部参数就会被忽略。 

// 否则的话, 值的 toString 方法将会被调用,并且使用调用结果。 
@GET("user") Call<User> getUsers(@Header("Authorization") String authorization);


然后是编写 Retrofit 对象类:

public class HttpClient{
private ApiService mApiService;
private static HttpClient mInstance;
private HttpClient(){
String baseUrl = HttpConfig.getUrl();
Retrofit retrofit = new Retrofit.Builder()
//添加url
.baseUrl(baseUrl)
//添加gson解析
.addConverterFactory(GsonConverterFactory.create())
.build();
mApiService = retrofit.create(ApiService.class);
}

public static HttpClient getInstance(){
if(mInstance==null){
mInstance=new HttpClient();
}
return mInstance;
}

public ApiService getApiService(){
return mApiService;
}
}


http 配置类

public class HttpConfig {

private static boolean IS_DEBUG=true;
private static String mBaseUrl=null;
private static final String TEST_URL="https://api.github.com/";
private static final String RELEASE_URL="";
public static String getUrl(){
if(IS_DEBUG){
mBaseUrl=TEST_URL;
}else{
mBaseUrl=RELEASE_URL;
}
return mBaseUrl;
}
}


现在以 发送一个获取 短信的通讯为例:

接口类中声明 url:

 //注册时获取短信验证码
@POST("api/login/pushSms")
@FormUrlEncoded
Call<ApiResponse<SmsCode>> postSms(@FieldMap Map<String, String> map);
ApiResponse和SmsCode 均为 实体model

在 activity中发起通讯并接收结果:

private void send(Map<String,String>map){
HttpClient.getInstance().getApiService().postSms(map).enqueue(new Callback<ApiResponse<SmsCode>>() {
@Override
public void onResponse(Call<ApiResponse<SmsCode>>call, Response<ApiResponse<SmsCode>>response) {
int code=response.code();
ApiResponse apiResponse=response.body();
SmsCode sms= (SmsCode) apiResponse.getData();

Log.e(TAG, "sms: "+sms.getStatus());
}

@Override
public void onFailure(Call call, Throwable t) {
Log.e(TAG, "t"+t.getMessage());
}
});
}


activity中点击 button 的时候,调用 send 方法并传入 map 参数即可,通讯返回结果如下:

test E/pei: sms: -1
test E/pei: code: ApiResponse{code=0, message='请求失败', data=com.test.model.SmsCode@61b3d8d}
test E/pei: code: 200


最后是关于Retrofit2.0的混淆

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

其实关于 Retrofit2.0,如果不需要对网络通讯做特殊处理,是不需要引入 okhttp3的,因为 Retrofit2.0 本身就是对 Okhttp3的一个封装,这是需要注意的。

ok,今天对于 Retrofit2.0 的讲解就到这里,感谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息