Retrofit 最簡單的快速入門及封裝
阿新 • • 發佈:2019-01-02
- Retrofit是Square公司開發的一款針對Android網路請求的框架,Retrofit2底層基於OkHttp實現的,OkHttp現在已經得到Google官方認可,大量的app都採用OkHttp做網路請求
- Retrofit也就成了最火的網路請求框架之一,想著來研究一下Retrofit了…先看了看官方文件,發現各種坑,Retrofit是結合著註解來做的,思路新穎,但是不符合大部分開發程式設計師的思維習慣,一開始使用的時候,不太適應…附上官方文件的介紹
Retrofit turns your HTTP API into a Java interface.
public interface GitHubService {
@GET ("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
The Retrofit class generates an implementation of the GitHubService interface.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class );
Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<List<Repo>> repos = service.listRepos("octocat");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
快速入門,從Hello 百度走起
- 想快速入門Retrofit,我們最簡單的想法是能請求一下www.baidu.com,然後將資訊列印一下,但是發現在Retrofit入門的時候,訪問www.baidu.com竟然成了奢求…,大部分的文章都是模仿著官方文件來寫的…
- 先一起來寫一個訪問百度,展示資料的示例
- 第一步:gradle檔案中進行配置
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta2'
compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
- 1
- 2
- 3
- 第二步:定義一個介面,介面中使用註解註明請求方式,及對應的請求路徑
public interface DataService {
//指定get請求方式 指定路徑 有時候路徑除了baseUrl還有一部分比如 http://write.blog.csdn.net/mdeditor
//http://write.blog.csdn.net/ 一般是baseUrl
//而 mdeditor是相對路徑的
@GET
Call<String> baidu(@Url String url);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 第二步:進行請求
//建立Retrofit物件
Retrofit retrofit = new Retrofit.Builder()
//指定baseurl,這裡有坑,最後字尾出帶著“/”
.baseUrl("http://www.baidu.com/")
//設定內容格式,這種對應的資料返回值是String型別
.addConverterFactory(ScalarsConverterFactory.create())
//定義client型別
.client(new OkHttpClient())
//建立
.build();
//通過retrofit和定義的有網路訪問方法的介面關聯
DataService dataService = retrofit.create(DataService.class);
//在這裡又重新設定了一下baidu的地址,是因為Retrofit要求傳入具體,如果是決定路徑的話,路徑會將baseUrl覆蓋掉
Call<String> baidu = dataService.baidu("http://wwww.baidu.com");
//執行非同步請求
baidu.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Toast.makeText(MainActivity.this, response.body(), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 通過上述程式碼,咱們就可以完整的看見百度的html介面了,算是對Retrofit做一個入門
其他請求-QQ吉凶測試
{"error_code":0,"reason":"success","result":{"data":{"conclusion":"[大吉+官運+財運+才藝]如龍得雲,青雲直上,智謀奮進,才略奏功","analysis":"慾望難足希望高,計謀成功財力豪,猜疑嫉妒性自改,如龍乘雲勢運開。智慧超人貫徹大志,富貴無比,不甘寂寞,叱吒風雲之大吉數,但容易發生牢騷及貪心、慾望太多而永不知足,為其缺點。切忌沉迷投機,可免貽誤前程。"}}}
- 1
對於Retrofit可以直接生成對應的json
第一步:生成對應的Bean,例如 QQData
第二步:在介面中定義請求方法
- GET請求
- 請求相對路徑
- 引數內容
- Call代表是一個請求
public interface DataService {
@GET("/qqevaluate/qq")
Call<QQData> getQQData(@Query("key") String appkey, @Query("qq") String qq);
}
- 1
- 2
- 3
- 4
- 5
- 第三步:開始請求
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://japi.juhe.cn")
.addConverterFactory(GsonConverterFactory.create()).build();
DataService dataService = retrofit.create(DataService.class);
final Call<QQData> qqData = dataService.getQQData("96efc220a4196fafdfade0c9d1e897ac", "11111111");
qqData.enqueue(new Callback<QQData>() {
@Override
public void onResponse(Response<QQData> response, Retrofit retrofit) {
String reason = response.body().getReason();
Toast.makeText(MainActivity.this, response.body().getReason(), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, "--" + t.getMessage().toString(), Toast.LENGTH_SHORT).show();
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 以上是Retrofit的簡單應用,當然對於Retrofit還有一些其他的方式
///https://zhidao.baidu.com/daily/view
//路徑拼接的形式,v代表是其中的一個引數,可以在這個位置進行拼接
@GET("daily/{v}")
Call<String> baiduzhidao(@Path("v") String v);
//在註解中指定路徑,定義相對應的引數的集合
@GET("qqevaluate/qq")
Call<QQData> getQQDataMap(@QueryMap Map<String,String> map);
//對應Post請求,引數的註解是@Field
@POST("qqevaluate/qq")
Call<QQData> postQQData(@Field("key") String key,@Field("qq") String qq);
//必須指定進行表單編碼
@FormUrlEncoded
//指定引數是map形式 @FieldMap
@POST("qqevaluate/qq")
Call<QQData> postQQDataMap(@FieldMap Map<String,String> map);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
自己封裝一個簡易的Retrofit請求
對於Retrofit,我們發現確實有一些特色,請求也比較簡單,但是,當在一個大的專案中,不可能每一請求都到介面中宣告一下。所以有必要進行簡易的封裝
封裝一個簡易的請求介面
public interface ProjectAPI {
//http://www.baidu.com/aaa?key=123&qq=aaa
@GET
Call<String> getMethod(@Url String url);
@FormUrlEncoded
@POST
Call<String> postMethod(@Url String url, @FieldMap Map<String,String> map);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 定義一個網路請求的管理類,需要注意的是這裡的baseUrl建立了,如果url是在其基礎上的,就會進行相應的拼接,如果url是全路徑,就會覆蓋掉baseUrl
public class HttpManger {
/**
* @param baseUrl 基礎Url
* @param url 附加Url
* @param callback 新增請求回撥,這裡直接使用的是Retrofit自身的回撥介面
*/
public static void getMethod(String baseUrl, String url, final Callback<String> callback) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).build();
ProjectAPI projectAPI = retrofit.create(ProjectAPI.class);
Call<String> call = projectAPI.getMethod(url);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
//呼叫回撥
callback.onResponse(call, response);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
//呼叫回撥
callback.onFailure(call, t);
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- Post請求方式的封裝,引數通過map集合的方式進行傳遞
public static void postMethod(String baseUrl, String url, Map<String, String> map, final Callback<String> callback) {
//指定客戶端
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient).addConverterFactory(ScalarsConverterFactory.create()).build();
ProjectAPI projectAPI = retrofit.create(ProjectAPI.class);
Call<String> call = projectAPI.postMethod(url, map);
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
callback.onResponse(call, response);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
callback.onFailure(call, t);
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 方法呼叫-Get方式呼叫,這裡的key大家可以替換一下
HttpManger.getMethod("http://japi.juhe.cn/", "http://japi.juhe.cn/qqevaluate/qq?key=96efc220a4196fafdfade0c9d1e897ac&qq=295424589", new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Toast.makeText(MainActivity.this, "--"+response.body(), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(MainActivity.this, "--"+t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- POST方式呼叫
Map<String, String> map=new HashMap<>();
map.put("key","96efc220a4196fafdfade0c9d1e897ac");
map.put("qq","111111111");
HttpManger.postMethod(false,false,"http://japi.juhe.cn/","qqevaluate/qq",map,new Callback<String>(){
@Override
public void onResponse(Call<String> call, Response<String> response) {
Toast.makeText(MainActivity.this, "--"+response.body(), Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<String> call, Throwable t) {
Toast.makeText(MainActivity.this, "--"+t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 正好最近做到了Cookie的應用,在本講解中進行一下講解
- 建立一個儲存Cookie的攔截器,用於獲取伺服器打給客戶端的Cookie資訊
public class SaveCookiesInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
//獲取到響應
Response originalResponse = chain.proceed(chain.request());
//進行Cookie獲取以及字串的拼接,Cookie在使用的過程要
//根據具體公司來定
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
//根據Set-Cookie獲取出的資訊
for (String header : originalResponse.headers("Set-Cookie")) {
Log.i("AAAA----","=="+header+"==");
String cookie = header.substring(0, header.indexOf(";") + 1);
stringBuilder.append(cookie);
}
}
//拼接時完成後將該Cookie儲存到 SharedPreferences中
SharedPreferencesUtils.saveString(MyApplication.context,"cookie",stringBuilder.toString());
return originalResponse;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 建立讀取Cookie的攔截器
public class ReadCookiesInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
String cookie = SharedPreferencesUtils.getString(MyApplication.context, "cookie", "");
//將cookie新增到請求頭中
builder.addHeader("Cookie", cookie);
return chain.proceed(builder.build());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 在HttpManager中指定攔截器的使用,但是並不是所有的請求都要儲存cookie或者所有的請求都要讀取cookie,所以我們新增一個判斷
/**
*
* @param isReadCookie 是否要讀取cookie
* @param isSaveCookie 是否要儲存cookie
* @param baseUrl 基礎Url
* @param url 要拼接的url
* @param map 引數集合
* @param callback 請求回撥
*/
public static void postMethod(boolean isReadCookie, boolean isSaveCookie, String baseUrl, String url, Map<String, String> map, final Callback<String> callback) {
OkHttpClient httpClient = null;
if (isReadCookie && !isSaveCookie) {
httpClient = new OkHttpClient.Builder()
.addInterceptor(new ReadCookiesInterceptor())
.build();
Log.i("AAA","只讀不寫");
}
if (isSaveCookie && !isReadCookie) {
httpClient = new OkHttpClient.Builder()
.addInterceptor(new SaveCookiesInterceptor())
.build();
Log.i("AAA","只寫不讀");
}
if (isSaveCookie && isReadCookie) {
httpClient = new OkHttpClient.Builder()
.addInterceptor(new SaveCookiesInterceptor()).addInterceptor(new ReadCookiesInterceptor())
.build();
Log.i("AAA","又寫又讀");
} if (!isSaveCookie && !isReadCookie){
httpClient = new OkHttpClient.Builder()
.build();
Log.i("AAA","不寫不讀");
}
//指定客戶端
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient).addConverterFactory(ScalarsConverterFactory.create()).build();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 好了,暫時寫到這裡,以上就是對Retrofit的一個簡易封裝,當然網上也有一些大神對Retrofit進行了封裝。