一:简介
Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,大量的app都采用OkHttp做网络请求,其源码详见OkHttp Github。
二:retrofit 的简单封装
- 1: 在具体介绍retrofit的用法之前,gradle配置(具体版本号参见官网)
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
- 2:这里有必要对baseUrl坐下解释,baseurl必须是以“/"结尾的,在我们定义请求的接口时,会传入具体的地址,retrofit会帮助我们完成拼接,最后形成完整url。
/**
* Created by Administrator on 2017/3/16.
*/
public class AppClient {
static Retrofit mRetrofit;
public static Retrofit retrofit() {
if (mRetrofit == null) {
/*
* 设置cookie
* */
OkHttpClient.Builder builder = new OkHttpClient.Builder();
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
builder.cookieJar(new JavaNetCookieJar(cookieManager))
.connectTimeout(30, TimeUnit.SECONDS) //设置超时
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)////失败重连
.addNetworkInterceptor(new Interceptor() { //有无网络都走缓存
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().build();
}
});
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
builder.sslSocketFactory(sslSocketFactory).hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
} catch (Exception e) {
e.printStackTrace();
} try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
builder.sslSocketFactory(sslSocketFactory).hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);//过滤https请求
} catch (Exception e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
// Log信息拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
TLog.analytics(message);
}
});
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//设置 Debug Log 模式
builder.addInterceptor(loggingInterceptor);
}
OkHttpClient okHttpClient = builder.build();
mRetrofit = new Retrofit.Builder()
.client(okHttpClient)// 设置client对象
.baseUrl("http://61.129.70.23:84/EasyRentService.svc/")// baseurl地址
.addConverterFactory(GsonConverterFactory.create()) //表示调用Gson库来解析json返回值
.build();
}
return mRetrofit;
}
public interface ApiStores {
/**
* post请求获取区域
*/
@POST("GetBigZoneInfos")
@FormUrlEncoded
Call<AreaBean> requestFansList(@Field("") String str);
/**
* json请求
* @param route
* @return
*/
@POST("HourseDetail")
Call<HouseDetailBean> gethouseDetail(@Body RequestBody route);
/**
* get请求
* @return
*/
@GET("index")
Call<GiftBean> getUsers();
}
}
三:Retrofit 用法实例
(一) :一般的get请求
- (1) 首先定义一个接口对象,定义请求方法,通过@GET方式表示为get请求, @GET中所填写的value和baseUrl组成完整的路径
public interface ApiStores {
/**
* get请求
* @return
*/
@GET("index")
Call<GiftBean> getData();
}
- 具体点业务逻辑代码
AppClient.ApiStores apiStores = AppClient.retrofit().create(AppClient.ApiStores.class);
Call<AreaBean> call = apiStores.getData();
call.enqueue(new Callback<GiftBean>() {
@Override
public void onResponse(Call<GiftBean> call, Response<GiftBean> response) {
Log.i("MainActivity", "normalGet:" + response.body() + "");
}
@Override
public void onFailure(Call<GiftBean> call, Throwable t) {
}
});
2. @Query(当然相同的方式也适用于POST,只需要把注解修改为@POST即可。)
Get方法请求参数都会以key=value的方式拼接在url后面
/**
*这里需要稍作说明,@GET注解就表示get请求,@Query表示请求参数,将会以key=value的方式拼接在url后面
/
public interface BlueService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("q") String name,
@Query("tag") String tag, @Query("start") int start,
@Query("count") int count);
}
此处最后得到的url完整地址为
https://api.douban.com/v2/book/search?q=%E5%B0%8F%E7%8E%8B%E5%AD%90&tag=&start=0&count=3
3. @QueryMap
如果Query参数比较多,那么可以通过@QueryMap方式将所有的参数集成在一个Map统一传递
public interface BlueService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options);
}
Map<String, String> options = new HashMap<>();
map.put("q", "小王子");
map.put("tag", null);
map.put("start", "0");
map.put("count", "3");
Call<BookSearchResponse> call = mBlueService.getSearchBooks(options);
4. Query集合
假如你需要添加相同Key值,但是value却有多个的情况,一种方式是添加多个@Query参数,还有一种简便的方式是将所有的value放置在列表中,然后在同一个@Query下完成添加
public interface BlueService {
@GET("book/search")
Call<BookSearchResponse> getSearchBooks(@Query("q") List<String> name);
}
最后得到的url地址为
https://api.douban.com/v2/book/search?q=leadership&q=beyond%20feelings
5. @Path
如果请求的相对地址也是需要调用方传递,那么可以使用@Path注解,示例代码如下:
@GET("book/{id}")
Call<BookResponse> getBook(@Path("id") String id);
具体代码
Call<BookResponse> call = mBlueService.getBook("1003078"
此时的url地址为
https://api.douban.com/v2/book/1003078
(二:)Post请求
1. @field(请求参数比较少)
@POST("oneselfmessage")
@FormUrlEncoded
Call<User> login(@Field("uid") String username);
2. @FieldMap
@FormUrlEncoded
@POST("book/reviews")
Call<String> addReviews(@FieldMap Map<String, String> fields);
3. @Body(向服务器传入json字符串)
@FormUrlEncoded
@POST("book/reviews")
Call<String> addReviews(@Body Reviews reviews);
public class Reviews {
public String book;
public String title;
public String content;
public String rating;
}
注意上述向服务器提交json字符串如果不行的话可以参考如下代码:
/**
* json请求
* @param route
* @return
*/
@POST("HourseDetail")
Call<HouseDetailBean> gethouseDetail(@Body RequestBody route);
具体代码
AppClient.ApiStores apiStores = AppClient.retrofit().create(AppClient.ApiStores.class);
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),
new Gson().toJson(new Enity("30921")));
Call<HouseDetailBean> call = apiStores.gethouseDetail(body);
call.enqueue(new Callback<HouseDetailBean>() {
@Override
public void onResponse(Call<HouseDetailBean> call, Response<HouseDetailBean> response) {
Log.i("MainActivity", "房屋详情:" + response.body() + "");
}
@Override
public void onFailure(Call<HouseDetailBean> call, Throwable t) {
;
}
});
其中的enty实例
public class Enity {
public String HouseId;
public Enity(String HouseId) {
this.HouseId = HouseId;
}
( 三):上传
1:单文件上传@Multipart
// 上传单个文件
@Multipart
@POST("modifyheadimg")
Call<BaseBean> uploadFile(
@Part("uid") RequestBody uid,
@Part MultipartBody.Part file);
//这里@MultiPart的意思就是允许多个@Part了,第二个我们准备上传个文件,使用了MultipartBody.Part类型,其余两个均为简单的键值对。
具体上传代码如下:
File file = new File(path);
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("img", file.getName(), photoRequestBody); //第一个参数是上传文件的key,第二个是文件的名字
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://114.55.128.82/20160507/Home/Member/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Controller userBiz = retrofit.create(Controller.class);
Call<BaseBean> call = userBiz.uploadFile(RequestBody.create(null, "10000367"),photo);
call.enqueue(new Callback<BaseBean>() {
@Override
public void onResponse(Call<BaseBean> call, Response<BaseBean> response) {
Log.i("MainActivity", "=======update========" + response.body() + "");
}
@Override
public void onFailure(Call<BaseBean> call, Throwable t) {
Log.i("MainActivity", "=======update失败========" + t + "");
}
});
2多文件上传
// 上传多个文件
@Multipart
@POST("upload")
Call<ResponseBody> uploadMultipleFiles(
@Part("description") RequestBody description,
@Part MultipartBody.Part file1,
@Part MultipartBody.Part file2);
具体的实例就不再一一举例了
(四):下载
@Streaming
@GET
Call<ResponseBody> downloadFile(@Url String url);//假如说你的某一个请求不是以base_url开头该怎么办呢?直接用@Url注解的方式传递完整的url地址即可。
具体代码
Call<ResponseBody> call = userBiz.downloadTest();
call.enqueue(new Callback<ResponseBody>()
{
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response)
{
InputStream is = response.body().byteStream();
//save file
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t)
{
}
});
(五)okHttp完美支持Https传输
http://blog.csdn.net/sk719887916/article/details/51597816
http://blog.csdn.net/duanyy1990/article/details/52139294
http://blog.csdn.net/lmj623565791/article/details/51304204
http://blog.csdn.net/u014695188/article/details/52985514
http://blog.csdn.net/u010286855/article/details/52608485
http://blog.csdn.net/dd864140130/article/details/52625666