Retrofit 最簡單的快速入門及自己封裝

簡單介紹及官方文檔的坑

  • 官方文檔 http://square.github.io/retrofit/
  • 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");

快速入門,從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'
  • 第二步:定義一個接口,接口中使用註解註明請求方式,及對應的請求路徑
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);
}
  • 第二步:進行請求

      //創建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) {

            }
        });
  • 通過上述代碼,咱們就可以完整的看見百度的html界面了,算是對Retrofit做一個入門

其他請求-QQ吉凶測試

{"error_code":0,"reason":"success","result":{"data":{"conclusion":"[大吉+官運+財運+才藝]如龍得雲,青雲直上,智謀奮進,才略奏功","analysis":"慾望難足希望高,計謀成功財力豪,猜疑嫉妒性自改,如龍乘雲勢運開。智能超人貫徹大志,富貴無比,不甘寂寞,叱吒風雲之大吉數,但容易發生牢騷及貪心、慾望太多而永不知足,爲其缺點。切忌沉迷投機,可免貽誤前程。"}}}

對於Retrofit可以直接生成對應的json

  • 第一步:生成對應的Bean,例如 QQData

  • 第二步:在接口中定義請求方法

    • GET請求
    • 請求相對路徑
    • 參數內容
    • Call代表是一個請求
public interface DataService {
    @GET("/qqevaluate/qq")
    Call<QQData> getQQData(@Query("key") String appkey, @Query("qq") String qq);
    }
  • 第三步:開始請求
 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();
            }
        });
  • 以上是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);

自己封裝一個簡易的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);

}
  • 定義一個網絡請求的管理類,需要注意的是這裏的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);
            }
        });
    }
  • 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);
            }
        });
    }
  • 方法調用-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();
            }
        });
  • 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();
            }
        });
  • 正好最近做到了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;
    }
}
  • 創建讀取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());
    }
}
  • 在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();
  • 好了,暫時寫到這裏,以上就是對Retrofit的一個簡易封裝,當然網上也有一些大神對Retrofit進行了封裝。

參考資料:
Retrofit 使用詳解http://blog.csdn.net/duanyy1990/article/details/52139294
Retrofit頂級封裝 http://blog.csdn.net/gengqiquan/article/details/52329259
github引用地址 https://github.com/gengqiquan/HttpUtil

發佈了62 篇原創文章 · 獲贊 132 · 訪問量 55萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章