Android應用層(網絡編程)五(Retrofit)

1. 使用前準備

Step 1: 向配置build.gradle:

dependencies {
  ...
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.retrofit2:converter-scalars:2.1.0'//ConverterFactory的String依賴包
}

Step 2: 在MainFest中加入訪問網絡的權限

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

Step 3: 查看淘寶IP地址庫的接口說明

1. 請求接口(GET):
/service/getIpInfo.php?ip=[ip地址字串]
2. 響應信息:
(json格式的)國家 、省(自治區或直轄市)、市(縣)、運營商
3. 返回數據格式:
{"code":0,"data":{"ip":"210.75.225.254","country":"\u4e2d\u56fd","area":"\u534e\u5317",
"region":"\u5317\u4eac\u5e02","city":"\u5317\u4eac\u5e02","county":"","isp":"\u7535\u4fe1",
"country_id":"86","area_id":"100000","region_id":"110000","city_id":"110000",
"county_id":"-1","isp_id":"100017"}}
其中code的值的含義爲,0:成功,1:失敗。

2.使用Retrofit異步訪問網絡

Step 1:編寫實體類

利用 JSON字符串轉換Java實體類 這個網站將JSON轉換爲實體類

public class JsonRootBean {

    private int code;
    private Data data;
    public void setCode(int code) {
         this.code = code;
     }
     public int getCode() {
         return code;
     }

    public void setData(Data data) {
         this.data = data;
     }
     public Data getData() {
         return data;
     }

}
public class Data {

    private String ip;
    private String country;
    private String area;
    private String region;
    private String city;
    private String county;
    private String isp;
    private String country_id;
    private String area_id;
    private String region_id;
    private String city_id;
    private String county_id;
    private String isp_id;
    public void setIp(String ip) {
         this.ip = ip;
     }
     public String getIp() {
         return ip;
     }

    public void setCountry(String country) {
         this.country = country;
     }
     public String getCountry() {
         return country;
     }

    public void setArea(String area) {
         this.area = area;
     }
     public String getArea() {
         return area;
     }

    public void setRegion(String region) {
         this.region = region;
     }
     public String getRegion() {
         return region;
     }

    public void setCity(String city) {
         this.city = city;
     }
     public String getCity() {
         return city;
     }

    public void setCounty(String county) {
         this.county = county;
     }
     public String getCounty() {
         return county;
     }

    public void setIsp(String isp) {
         this.isp = isp;
     }
     public String getIsp() {
         return isp;
     }

    public void setCountry_id(String country_id) {
         this.country_id = country_id;
     }
     public String getCountry_id() {
         return country_id;
     }

    public void setArea_id(String area_id) {
         this.area_id = area_id;
     }
     public String getArea_id() {
         return area_id;
     }

    public void setRegion_id(String region_id) {
         this.region_id = region_id;
     }
     public String getRegion_id() {
         return region_id;
     }

    public void setCity_id(String city_id) {
         this.city_id = city_id;
     }
     public String getCity_id() {
         return city_id;
     }

    public void setCounty_id(String county_id) {
         this.county_id = county_id;
     }
     public String getCounty_id() {
         return county_id;
     }

    public void setIsp_id(String isp_id) {
         this.isp_id = isp_id;
     }
     public String getIsp_id() {
         return isp_id;
     }

}

Step 2:請求網絡連接

Retrofit提供的請求方式註解有@GET和@POST等。

public interface IpService{
    @GET("getIpInfo.php")
    Call<JsonRootBean> getIpMsg(@Query("ip")String ip);
}

我們在這裏訪問的界面是“getIpInfo.php”。參數註解有@PATH和@Query等,@Query就是我們的請求的鍵值對的設置,在這裏@Query(“ip”)代表鍵,“String ip”則代表值。

Step 3:創建Retrofit

String url = "http://ip.taobao.com/service/";
     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl(url)
             //增加返回值爲String的支持
             .addConverterFactory(ScalarsConverterFactory.create())
             .addConverterFactory(GsonConverterFactory.create())
             .build();

這裏的baseUrl加上之前@GET(“getIpInfo.php”)定義的參數形成完整的請求地址;addConverterFactory用於指定返回的參數數據類型,這裏我們支持String和Gson類型。

Step 4: 用Retrofit創建接口文件

IpService ipService = retrofit.create(IpService.class);
Call<IpModel>call=ipService.getIpMsg(ip);

用retrofit創建我們之前定義的IpService接口對象,並調用該接口定義的getIpMsg方法得到Call對象。

Step 5:用Call請求網絡並處理回調

call.enqueue(new Callback<IpModel>() {
           @Override
           public void onResponse(Call<IpModel> call, Response<IpModel> response) {
              String country= response.body().getData().getCountry();
               Log.i("wangshu","country"+country);
               Toast.makeText(getApplicationContext(),country,Toast.LENGTH_SHORT).show();
           }
           @Override
           public void onFailure(Call<IpModel> call, Throwable t) {
           }
       });

這裏是異步請求網絡,回調的Callback是運行在主線程的。得到返回的Response後將返回數據的country字段用Toast顯示出來。如果想同步請求網絡請使用 call.execute(),如果想中斷網絡請求則可以使用 call.cancel()。

Step Last:完整的代碼:

public class MainActivity extends AppCompatActivity {
    private Button bt_request;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_request = (Button) findViewById(R.id.bt_request);
        bt_request.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getIpInformation("59.108.54.37");
            }
        });
    }
    private void getIpInformation(String ip) {
        String url = "http://ip.taobao.com/service/";
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                //增加返回值爲String的支持
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        IpService ipService = retrofit.create(IpService.class);
        Call<IpModel>call=ipService.getIpMsg(ip);
        call.enqueue(new Callback<IpModel>() {
            @Override
            public void onResponse(Call<IpModel> call, Response<IpModel> response) {
               String country= response.body().getData().getCountry();
                Log.i("wangshu","country"+country);
                Toast.makeText(getApplicationContext(),country,Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onFailure(Call<IpModel> call, Throwable t) {
            }
        });
    }

3. 請求參數

請求方法除了上文講到的@GET,還有@POST、@PUT、@DELETE、@HEAD、@OPTIONS、@PATCH、@HTTP。其中@HTTP用來替換以上7個,其他的分別對應着不同的請求方法,不明白的請查看Android網絡編程(一)HTTP協議原理這一篇文章。

@Query

前面的例子就用了Query用來查詢參數。

public interface IpService{
    @GET("getIpInfo.php")
    Call<IpModel> getIpMsg(@Query("ip")String ip);
}

@QueryMap

如果Query參數比較多,那麼可以通過@QueryMap方式將所有的參數集成在一個Map統一傳遞。

public interface BlueService {
    @GET("book/search")
    Call<BookSearchResponse> getSearchBooks(@QueryMap Map<String, String> options);
}

@Path

@Path用來替換路徑。

public interface ApiStores {
    @GET("adat/sk/{cityId}.html")
    Call<ResponseBody> getWeather(@Path("cityId") String cityId);
}

@Body

@Body與@POST註解一起使用,提供查詢主體內容,其中ApiInfo是一個bean類。

public interface ApiStores {
        @POST("client/shipper/getCarType")
        Call<ResponseBody> getCarType(@Body ApiInfo apiInfo);
    }

@Headers

interface SomeService {
 @GET("some/endpoint")
 @Headers("Accept-Encoding: application/json")
 Call<ResponseBody> getCarType();
}

@Headers用來添加頭部信息,上面用的是固定頭部,也可以採用動態頭部:

interface SomeService {
 @GET("some/endpoint")
 Call<SomeResponse> someEndpoint(
 @Header("Location") String location);
}

@Multipart

@Multipart用來上傳文件

public interface FileUploadService {  
    @Multipart
    @POST("upload")
    Call<ResponseBody> upload(@Part("description") RequestBody description,
                              @Part MultipartBody.Part file);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章