Android小白之retrofit實現號碼歸屬地查詢

weixin_34308389發表於2017-08-02

簡介

retrofit是square公司研發的一個開源的庫,它是目前Android開發使用最流行的http client庫之一,它主要用來簡化APP訪問伺服器API,底層是使用okhttp封裝的,網路請求速度很快。使用retrofit的前提是服務端程式碼需要遵循REST規範。接下來就通過一個具體的例子來完成對retrofit的一個基本使用。我們通過使用retrofit來請求服務端,解析返回的json資料,來完成手機號碼歸屬地的查詢。

效果圖:

4012813-e47be5846fbcaf88.gif
GIF1.gif

手機號碼歸屬地介面介紹:

在編寫Demo之前,先來提供一個免費的API-手機號碼歸屬地介面,它可以根據手機號碼或手機號碼的前7位,查詢手機號碼歸屬地資訊,包括省份 、城市、區號、郵編、運營商和卡型別。

介面文件:https://www.juhe.cn/docs/api/id/11
要使用的話,需要先申請APPKEY,通過稽核,之後就可以無限次免費使用。

  1. API簡單介紹:

  2. 程式碼示例:手機號碼歸屬地介面呼叫示例

retrofit的功能 :

  • 可以直接將結果轉換稱Java類
  • 主要是配合RxJava一起使用
  • 請求效率高

retrofit使用簡介:

  1. 新增依賴:

     //新增依賴,新增butterknife,省去findViewById操作
     compile 'com.squareup.okhttp3:okhttp:3.2.0'
     compile 'com.squareup.retrofit2:retrofit:2.1.0'
     compile 'com.google.code.gson:gson:2.2.4'
     compile 'com.squareup.retrofit2:converter-gson:2.1.0'
     compile 'com.jakewharton:butterknife:7.0.1'
    
  2. 定義相應資料的JavaBean(根據分析返回的json資料來定義ResponseInfo類):

     public class ResponseInfo {
     
         /**
          * resultcode : 200
          * reason : Return Successd!
          * result : {"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移動","card":""}
          * error_code : 0
          */
     
         private String resultcode;
         private String reason;
         private ResultBean result;
         private int error_code;
     
         public String getResultcode() {
             return resultcode;
         }
     
         public void setResultcode(String resultcode) {
             this.resultcode = resultcode;
         }
     
         public String getReason() {
             return reason;
         }
     
         public void setReason(String reason) {
             this.reason = reason;
         }
     
         public ResultBean getResult() {
             return result;
         }
     
         public void setResult(ResultBean result) {
             this.result = result;
         }
     
         public int getError_code() {
             return error_code;
         }
     
         public void setError_code(int error_code) {
             this.error_code = error_code;
         }
     
         public static class ResultBean {
             /**
              * province : 浙江
              * city : 杭州
              * areacode : 0571
              * zip : 310000
              * company : 移動
              * card :
              */
     
             private String province;
             private String city;
             private String areacode;
             private String zip;
             private String company;
             private String card;
     
             public String getProvince() {
                 return province;
             }
     
             public void setProvince(String province) {
                 this.province = province;
             }
     
             public String getCity() {
                 return city;
             }
     
             public void setCity(String city) {
                 this.city = city;
             }
     
             public String getAreacode() {
                 return areacode;
             }
     
             public void setAreacode(String areacode) {
                 this.areacode = areacode;
             }
     
             public String getZip() {
                 return zip;
             }
     
             public void setZip(String zip) {
                 this.zip = zip;
             }
     
             public String getCompany() {
                 return company;
             }
     
             public void setCompany(String company) {
                 this.company = company;
             }
     
             public String getCard() {
                 return card;
             }
     
             public void setCard(String card) {
                 this.card = card;
             }
         }
     }
    
  3. 定義java介面描述⽹絡請求介面的API,在java介面中的方法和引數上新增註解來描述api:

     public interface ResponseInfoAPI {
         /**
         * @GET ----註解描述 API 請求的⽅式
         * @GET("/mobile/get") ----註解中的引數描述請求 URL 中的路徑
         * @Query ----註解描述請求 URL 中的引數
         * 
          * @Path - 替換引數
              @GET("/group/{id}/users")
              public Call<List<User>> groupList(@Path("id") int groupId);
    
          * @Query - 新增查詢引數
              @GET("/group/{id}/users")
              public Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
    
          * @QueryMap - 如果有多個查詢引數,把它們放在Map中
              @GET("/group/{id}/users")
              public Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
          */
     
         @GET("/mobile/get")
         Call<ResponseInfo> getLocation(@Query("phone") String phone,@Query("key") String key);
     }
    
  4. 接下來就需要建立retrofit物件,api介面物件,呼叫介面方法建立call物件。最後就是呼叫call.enqueue()方法發起非同步網路請求,返回處理結果。

     //建立retrofit物件
     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl(BASEURL)
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     //建立api介面的物件
     ResponseInfoAPI responseInfoAPI = retrofit.create(ResponseInfoAPI.class);
    
     //呼叫介面方法建立call物件
     String num = etNum.getText().toString().trim();
     String key = "72f71cc5a57f3c9dda1e612105b95a70";
    
     Call<ResponseInfo> getLocation = responseInfoAPI.getLocation(num,key);
    
    
     //呼叫execute()發起同步請求,由於在主執行緒,執行會報異常
     //getLocation.execute();
     //呼叫Call.enqueue()方法發起非同步網路請求,可以直接在主執行緒中執行
     getLocation.enqueue(new Callback<ResponseInfo>() {
         @Override
         public void onResponse(Call<ResponseInfo> call, Response<ResponseInfo> response) {
             ResponseInfo body = response.body();
             tvAddress.setText("歸屬地:" +body.getResult().getProvince() +
                     "." + body.getResult().getCity());
             tVCompany.setText("運營商:" + body.getResult().getCompany());
         }
    
         @Override
         public void onFailure(Call<ResponseInfo> call, Throwable t) {
             tvAddress.setText(t.toString());
             tVCompany.setVisibility(View.GONE);
         }
     });
    
  5. 還有最重要的一步:新增網路許可權:

     <uses-permission android:name="android.permission.INTERNET"/>
    

之後將專案執行到真機上就可以實現效果。

Retrofit2.0的一些改進:

  1. 新增依賴匯入retrofit2.0:

     compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
    
  2. 新的service介面定義方式,不在有同步非同步之分:

     import retrofit.Call;
    
     /* Retrofit 2.0 */
      
     public interface APIService {
      
         @POST("/list")
         Call<Repo> loadRepo();
     }
    

呼叫同步請求只需要呼叫execute()方法,非同步請求呼叫exqueue()方法。

    //同步請求
    Call<Repo> call = service.loadRepo();
    Repo repo = call.execute();
    
     //非同步請求
    Call<Repo> call = service.loadRepo();
    call.enqueue(new Callback<Repo>() {
        @Override
        public void onResponse(Response<Repo> response) {
            // Get result Repo from response.body()
        }
     
        @Override
        public void onFailure(Throwable t) {
     
        }
    });
  1. 需要OKhttp的支援:

    在Retrofit 2.0中,OkHttp 是必須的,並且自動設定為了依賴。之前想讓retrofit使用OKhttp作為http的連線介面,需要手動新增依賴。

  2. 缺少INTERNET許可權會導致SecurityException異常:

    在Retrofit 2.0中,當你呼叫call.enqueue或者call.execute,將立即丟擲SecurityException,如果你不使用try-catch會導致崩潰。

  3. 使用OkHttp裡面的Interceptor攔截一個請求 :

     //首先你需要使用Interceptor建立一個OkHttpClient物件
     OkHttpClient client = new OkHttpClient();
     client.interceptors().add(new Interceptor() {
         @Override
         public Response intercept(Chain chain) throws IOException {
             Response response = chain.proceed(chain.request());
      
             // Do anything with response here
      
             return response;
         }
     });
    
     //然後傳遞建立的client到Retrofit的Builder鏈中
     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("http://api.nuuneoi.com/base/")
             .addConverterFactory(GsonConverterFactory.create())
             .client(client)
             .build();
    
  4. Retrofit 2.0不再依賴於Gson:

    如果你想接收json 結果並解析成DAO,你必須把Gson Converter 作為一個獨立的依賴新增進來。

     compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
    

完結

相關文章