一:簡介
Retrofit是Square公司開發(fā)的一款針對Android網(wǎng)絡(luò)請求的框架怎棱,Retrofit2底層基于OkHttp實現(xiàn)的,OkHttp現(xiàn)在已經(jīng)得到Google官方認可猪勇,大量的app都采用OkHttp做網(wǎng)絡(luò)請求,其源碼詳見OkHttp Github。
二:retrofit 的簡單封裝
- 1: 在具體介紹retrofit的用法之前膀值,gradle配置(具體版本號參見官網(wǎng))
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必須是以“/"結(jié)尾的创橄,在我們定義請求的接口時,會傳入具體的地址莽红,retrofit會幫助我們完成拼接妥畏,最后形成完整url。
/**
* Created by Administrator on 2017/3/16.
*/
public class AppClient {
static Retrofit mRetrofit;
public static Retrofit retrofit() {
if (mRetrofit == null) {
/*
* 設(shè)置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) //設(shè)置超時
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)////失敗重連
.addNetworkInterceptor(new Interceptor() { //有無網(wǎng)絡(luò)都走緩存
@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);
//設(shè)置 Debug Log 模式
builder.addInterceptor(loggingInterceptor);
}
OkHttpClient okHttpClient = builder.build();
mRetrofit = new Retrofit.Builder()
.client(okHttpClient)// 設(shè)置client對象
.baseUrl("http://61.129.70.23:84/EasyRentService.svc/")// baseurl地址
.addConverterFactory(GsonConverterFactory.create()) //表示調(diào)用Gson庫來解析json返回值
.build();
}
return mRetrofit;
}
public interface ApiStores {
/**
* post請求獲取區(qū)域
*/
@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();
}
- 具體點業(yè)務(wù)邏輯代碼
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方法請求參數(shù)都會以key=value的方式拼接在url后面
/**
*這里需要稍作說明,@GET注解就表示get請求妇智,@Query表示請求參數(shù)滥玷,將會以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參數(shù)比較多氏身,那么可以通過@QueryMap方式將所有的參數(shù)集成在一個Map統(tǒng)一傳遞
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參數(shù)蛋欣,還有一種簡便的方式是將所有的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
如果請求的相對地址也是需要調(diào)用方傳遞如贷,那么可以使用@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(請求參數(shù)比較少)
@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(向服務(wù)器傳入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;
}
注意上述向服務(wù)器提交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); //第一個參數(shù)是上傳文件的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