Retrofit 2.0 使用總結

這天,leader給了我一張圖,然後讓我調試後臺接口,圖片如下:
後臺接口

我看這麼簡單,然後直接用瀏覽器測試了一下,然後返回圖片如下:

這裏寫圖片描述
然後花了一個下午時間測試,終於把接口調通了,但是居然解析不了其中的返回內容,,,,於是,在禮拜天我就花時間來研究了一下關於接口的開發!
本來我打算隨便寫一個 Java 類,然後用tomcat就可以測試後臺了,但是我不知道如何實現上圖的禁止get請求,於是問了一下這方面的大神:

我用spring mvc的時候,controler的requestmapping的method 的值設爲post就會無視get請求

由於上面的知識點我都不會,於是我自動忽略了自己寫後臺的想法,接着打算在網上找一個可以測試後臺的網站,結果找到一個 http://www.ouapi.com/ ,但是打開頁面以後也不知道如何設置後臺,後來詢問大神得知——人家一般使用的是 postman 這個插件,於是我按照網上的介紹,趕緊安裝了一個!測試了一下,還真的很好用,以圖爲證:
這裏寫圖片描述
廢話說了這麼多,接下來開始幹正事!介紹一下自己使用 Retrofit 2.0 的一些總結。第一步,肯定是得導包,這個隨便百度一下 Retrofit 2.0 就可以翻出來了,

compile 'com.squareup.retrofit2:retrofit:2.0.2'  //retrofit:2.0
compile 'com.squareup.retrofit2:converter-gson:2.0.2'   //retrofit:2.0封裝下的gson
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'    //retrofit:2.0下的okhttp3的請求日誌

第二步就是實例化 retrofit ,這個基本上也是可以直接從網上複製下來就可以用

  HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(true)
                .connectTimeout(15, TimeUnit.SECONDS)
                .addNetworkInterceptor(interceptor)
                .build();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        //獲取實例
        Retrofit retrofit = new Retrofit.Builder()
                //設置OKHttpClient,如果不設置會提供一個默認的
                .client(client)
                //設置baseUrl,必須是以“/”結尾
                .baseUrl(url)
                //添加Gson轉換器
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

接下來就是關於各種網絡請求的封裝了,比如我們先請求一段本地的文件,測試一下 get 請求,簡單來說我們的第三步需要如下步驟:

  1. 建立 interface ,並封裝 get 請求
  2. 通過上面實例化的 Retrofit 對象,實例化上面的 interface 對象
  3. 調用上述封裝的 get 請求

    通過上面的步驟,大概知道做什麼以後,那麼我們通過 postman 來測試一下這個接口:
    get 請求
    當然,大家也可以通過post來測試這個接口,待會我們就可以來測試,現在開始來執行上面的第一步——建立 interface ,並封裝 get 請求:

public interface RetrofitInterface {

    @GET("getdata.gson")
    Call<Password> getPassWord();

}

這裏說一下 @GET(“getdata.gson”) 這裏爲什麼會跟一個文件呢?因爲上面說過,

設置baseUrl,必須是以“/”結尾(重要的事情只說一邊!)

所以我們現在帶着上面的提醒來執行第二步——通過上面實例化的 Retrofit 對象,實例化上面的 interface 對象:

/**
 * Retrofit實體類
 * Created by asus on 2017/7/15.
 */

public class RetrofitLoader {

    private RetrofitInterface service;

    public RetrofitLoader(String url){
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(true)
                .connectTimeout(15, TimeUnit.SECONDS)
                .addNetworkInterceptor(interceptor)
                .build();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        //獲取實例
        Retrofit retrofit = new Retrofit.Builder()
                //設置OKHttpClient,如果不設置會提供一個默認的
                .client(client)
                //設置baseUrl,必須是以“/”結尾
                .baseUrl(url)
                //添加Gson轉換器
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        service = retrofit.create(RetrofitInterface.class);

    }

   public void getPassWord(Callback<Password> callback){

        Call<Password> call = service.getPassWord();
        //異步請求
        call.enqueue(callback);
        //同步請求
        //1call.execute();

    }


}

上面的 RetrofitLoader 應該做一個單例,這裏只是測試,下來後慢慢完善!接下來就是第三步——調用上述封裝的 get 請求:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView textView = (TextView) findViewById(R.id.textview);

        Thread thread = Thread.currentThread();
        Log.e(TAG, "onCreate: "+ thread.getId());
        new Thread(){
            @Override
            public void run() {
                super.run();
                Thread thread = Thread.currentThread();
                Log.e(TAG, "run1: "+ thread.getId());

                 new RetrofitLoader("http://192.168.199.237:8080/examples/").getPassWord(new Callback<Password>() {
                     @Override
                     public void onResponse(Call<Password> call,final Response<Password> response) {
                         textView.setText(response.body().getData());
                         Thread thread = Thread.currentThread();
                         Log.e(TAG, "onResponse: "+ thread.getId());
                         textView.post(new Runnable() {
                             @Override
                             public void run() {

                                 Thread thread = Thread.currentThread();
                                 Log.e(TAG, "run2: "+ thread.getId());
                             }
                         });
                     }

                     @Override
                     public void onFailure(Call<Password> call, Throwable t) {
                         Log.e(TAG, "onFailure: ",t );
                     }
                 });
            }
        }.start();
    }
}

接下來我們看看日誌:

07-16 21:52:35.837 9174-9174/? E/MainActivity: onCreate: 1
07-16 21:52:35.838 9174-9195/? E/MainActivity: run1: 1248
07-16 21:52:36.076 9174-9174/? E/MainActivity: onResponse: 1
07-16 21:52:36.076 9174-9174/? E/MainActivity: onResponse: 7B7F25D86267923209A11145A4EBB34
07-16 21:52:36.086 9174-9174/? E/MainActivity: run2: 1

這裏說明一個問題:在線程裏面開子線程請求網絡(線程 ID :1248 ),然後異步返回的線程不是在當前所在的子線程,而是在主線程,至於網絡請求的同步,這個就不記錄測試了,其實我最想測試的是 Post 請求,而且是帶參數的,因爲工作中需要用到,但是在測試過程中發生問題了!
在講問題之前先看看API吧,如圖:
這裏寫圖片描述
接下來我們先封裝一個 Post 請求,不過這裏不需要單獨新建 interface 對象了,

/**
 * Created by asus on 2017/7/15.
 */

public interface RetrofitInterface {

    @GET("getdata.gson")
    Call<Password> getPassWord();
    @POST("LookUp")
    Call<IdCardResult> checkIdCard(@Body IdCardInfo cardInfo);
}


/**
 * Retrofit實體類
 * Created by asus on 2017/7/15.
 */

public class RetrofitLoader {


    private RetrofitInterface service;

    public RetrofitLoader(String url){
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .retryOnConnectionFailure(true)
                .connectTimeout(15, TimeUnit.SECONDS)
                .addNetworkInterceptor(interceptor)
                .build();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                .create();

        //獲取實例
        Retrofit retrofit = new Retrofit.Builder()
                //設置OKHttpClient,如果不設置會提供一個默認的
                .client(client)
                //設置baseUrl,必須是以“/”結尾
                .baseUrl(url)
                //添加Gson轉換器
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        service = retrofit.create(RetrofitInterface.class);

    }

    public void getPassWord(Callback<Password> callback){

        Call<Password> call = service.getPassWord();
        //異步請求
        call.enqueue(callback);
        //同步請求
        //1call.execute();

    }

    public void checkIdCard(IdCardInfo cardInfo, Callback<IdCardResult> callback){
        service.checkIdCard(cardInfo).enqueue(callback);
    }
}

接下來我們看看調用過程中是不是有傳說的異常?
訪問成功了
訪問成功了?那麼我們繼續來看看訪問不成功,只要將post方法修改一下,這個方法就運行不起來:

Call<Response> checkIdCard(@Body IdCardInfo cardInfo);

這裏寫圖片描述

雖然 Body 標籤完成了訪問,但是返回碼是 1001,返回碼是 key 值錯誤,但是這個值我確定沒有複製錯,具體是怎麼回事呢?看看日誌:
這裏寫圖片描述

對 http 來說參數之間的分割只有一種 & ,這裏的,是錯誤的,所以服務端報錯,那麼這裏該如何修改呢?

 @FormUrlEncoded
    @POST("LookUp")
    Call<IdCardResult> checkIdCard(@FieldMap Map<String, String> infos);

 public void checkIdCard(IdCardInfo cardInfo, Callback<IdCardResult> callback){
        Map<String, String> infos = new HashMap<>();
        infos.put("id",cardInfo.getId());
        infos.put("key",cardInfo.getKey());
        service.checkIdCard(infos).enqueue(callback);
    }

接下來我們再繼續觀察一下日誌:

07-16 23:25:18.385 19518-19555/? E/MainActivity: log: --> POST http://api.avatardata.cn/IdCard/LookUp http/1.1
07-16 23:25:18.385 19518-19555/? E/MainActivity: log: Content-Type: application/x-www-form-urlencoded
07-16 23:25:18.386 19518-19555/? E/MainActivity: log: Content-Length: 58
07-16 23:25:18.387 19518-19555/? E/MainActivity: log: 
07-16 23:25:18.387 19518-19555/? E/MainActivity: log: id=510921199103210310&key=af43ed19e5524c55a7bdb33d7f16bc5f
07-16 23:25:18.387 19518-19555/? E/MainActivity: log: --> END POST (58-byte body)
07-16 23:25:18.819 19518-19555/? E/MainActivity: log: <-- 200 OK http://api.avatardata.cn/IdCard/LookUp (432ms)
07-16 23:25:18.819 19518-19555/? E/MainActivity: log: Cache-Control: private
07-16 23:25:18.819 19518-19555/? E/MainActivity: log: Content-Length: 110
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: Content-Type: application/json; charset=utf-8
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: Server: Microsoft-IIS/7.5
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: X-AspNet-Version: 4.0.30319
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: X-Powered-By: ASP.NET
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: Date: Sun, 16 Jul 2017 15:25:19 GMT
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: OkHttp-Sent-Millis: 1500218718478
07-16 23:25:18.820 19518-19555/? E/MainActivity: log: OkHttp-Received-Millis: 1500218718818
07-16 23:25:18.821 19518-19555/? E/MainActivity: log: 
07-16 23:25:18.821 19518-19555/? E/MainActivity: log: {"result":{"address":"四川省蓬溪縣","sex":"M","birthday":"1991-03-21"},"error_code":0,"reason":"Succes"}
07-16 23:25:18.821 19518-19555/? E/MainActivity: log: <-- END HTTP (110-byte body)
07-16 23:25:18.830 19518-19518/? E/MainActivity: onResponse: 0

OK,明天可以給領導交差了!!!

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