Retrofit網絡框架入門使用

1.簡單介紹

retrofit事實上就是對okhttp作了進一步一層封裝優化。php

咱們僅僅需要經過簡單的配置就能使用retrofit來進行網絡請求了。css

Retrofit可以直接返回Bean對象,好比假設咱們進行一個網絡接口的請求。返回來一串json字符串。那麼這個時候通常咱們都要拿到這個json字符串後進行解析獲得相應的Bean對象,Retrofit僅僅要依賴一下Gson的轉換庫而後進行簡單的配置就可以直接拿到Bean對象了,不需要咱們本身去解析。html

接觸過OKHttp的人會發現,Retrofit和OKHttp的代碼有些地方有很大的相似度。java

他的性能很的棒,國外大牛(被牆了)已經作過測例如如下圖:android

這裏寫圖片描寫敘述

看了這個圖以後你有什麼想法?ios

Talk is cheap, show me the code!git

github

2.高速使用

在實際項目開發中get、post請求使用居多。那咱們以get請求來作個入門小案例。json

http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8

以上鍊接是一個get請求方式。參數在地址後面使用「?」進行名值對的拼接。請求的結果是一個json字符串數據。例如如下api

{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.8.8.8"}}

來個簡單的Demo界面例如如下:
功能很easy,一個輸入框輸入IP地址,而後獲取IP地址所在的國家。


這裏寫圖片描寫敘述

1)環境的配置

現在預計不多人用eclipse作項目開發了。eclipse的方式就不另贅述了(GitHub上也是有jar依賴下載的)。咱們這裏的開發工具是用的Android Studio,在 GitHub項目地址:https://github.com/square/retrofit可以找到Gradle的依賴代碼:
加入兩個依賴:retrofit依賴。和gson轉換器。

compile 'com.squareup.retrofit2:retrofit:2.1.0'//眼下最新的版本號
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//加入好這個依賴後咱們就可以進行數據轉換器的配置了。retrofit內部就會幫咱們去轉換json字符串爲Java對象

在AS裏面的效果例如如下:
這裏寫圖片描寫敘述

converter-gson依賴的版本號號與retrofit依賴版本號號保持一致。咱們在GitHub上可以看到。他們在同一個project裏面的。

2)代碼

佈局很easy就不另貼代碼了。類也很少參看如下的包結構圖
這裏寫圖片描寫敘述

Retrofit操做步驟

① 先把接口返回來的數據bean對象寫好。

可以直接使用工具轉化。如GsonFormat工具

public class IpInfo {
    public int code;
    public DataBean data;

    public static class DataBean {
        public String country;
        public String country_id;
        public String area;
        public String area_id;
        public String region;
        public String region_id;
        public String city;
        public String city_id;
        public String county;
        public String county_id;
        public String isp;
        public String isp_id;
        public String ip;

    }

}
② 定義API接口

通常來說都是處理遵循RESTful接口規範的http接口,咱們需要把接口轉化爲Java Interface。

/** * 這個接口就是普通的藉口類,但是看到裏面的方法來,會有一些註解定義相關的功能 * 如@GET定義請求方式爲get請求方式,假設有參數可以使用@Query、@QueryMap定義 */ public interface IpService { /** * @return 固定返回值爲Call。當中泛型指定是進行請求後返回終於得數據類型。

*/ @GET("getIpInfo.php") //@GET 定義網絡請求方式 Call<IpInfo> getIpInfo(@Query("ip") String ip); //@Query("ip") 指的是傳入的參數名爲ip。值爲調用方法傳入的值形參ip }
③ 初始化Retrofit,建立接口實例,進行異步請求

代碼凝視灰常仔細了

/** *Retrofit簡單有用案例 * * 採用http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.2 地址進行查詢 */ public class MainActivity extends AppCompatActivity { public static final String baseUrl = "http://ip.taobao.com/service/"; private TextView tvResult; private EditText etIp; IpService ipService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvResult = (TextView) findViewById(R.id.tv_result); etIp = (EditText) findViewById(R.id.et_ip); initRetrofit(); } /** * 初始化Retrofit實例。並建立接口類。 * 注意:IpService不需要咱們去實現。直接Retrofit=類有create方法生成。 */ private void initRetrofit() { //建立Retrofit的實例,把Gson轉換器設置下 Retrofit retrofit = new Retrofit .Builder() .baseUrl(baseUrl)//設置API的基礎地址 .addConverterFactory(GsonConverterFactory.create())//設置後才才支持json字符串轉化爲Bean .build(); //使用Retrofit的create方法傳入建立接口實例 ipService = retrofit.create(IpService.class); } /** * 佈局中查詢button配置的點擊事件 * @param view */ public void check(View view) { String ip = etIp.getText().toString(); if (TextUtils.isEmpty(ip)) { Toast.makeText(this, "ip 不能爲空", Toast.LENGTH_SHORT).show(); return; } //調用接口聲明的方法 Call<IpInfo> ipInfoCall = ipService.getIpInfo(ip); //call可以直接調用異步方法。進行結果獲取。

需要傳入接口回調Callback, ipInfoCall.enqueue(new Callback<IpInfo>() { @Override public void onResponse(Call<IpInfo> call, Response<IpInfo> response) { //推斷網絡請求是否成功。網絡請求返回code爲[200..300)那麼與後臺鏈接成功。

不然鏈接失敗 if (response.isSuccessful()) { //直接拿到JavaBean IpInfo ipInfo = response.body(); //這裏直接可以進行UI操做。OKHttp是不行的哦 tvResult.setText(ipInfo.getData().getCountry()); } else { //請求失敗。

假設代碼執行到這裏來講明是有跟後臺握手的,是後臺處理有問題,如404(沒有資源),500(後臺報錯了) tvResult.setText("查詢失敗!! -->code="+response.code()); } } @Override public void onFailure(Call<IpInfo> call, Throwable t) { //請求失敗。如,沒有聲明網絡權限、沒有網絡、或者是Retrofit 異常內部處理異常(如Gson解析失敗)也是會到這裏 t.printStackTrace(); tvResult.setText("查詢失敗:"+t.getCause()); } }); } }

3.常常使用註解

GET:get 請求方式
POST:post請求方式
Query:定義get請求參數
QueryMap:定義get請求參數
Field:定義post請求參數
FieldMap:定義post請求參數
Header:定義頭參數
HeaderMap:定義頭參數
Headers:定義頭參數
Path:動態路徑
來看看代碼是怎麼實現的:

public interface SampleApi { //----------------------GET 請求方式 start -------------------------------- /** * 註解:GET。QUERY,QUERYMAP 的使用 */ /** * get 請求固定參數形式 * * @return */ @GET("demo?

username=zhanghsan&password=123455") Call<SampleResponse> getFun(); /** * 使用@Query註解進行參數傳遞 * * @param username * @param password * @return */ @GET("demo") Call<SampleResponse> getFun(@Query("username") String username, @Query("password") String password); /** * 使用@QueryMap註解 Map集合進行參數傳遞 * * @param params * @return */ @GET("demo") Call<SampleResponse> getFun(@QueryMap Map<String, Object> params); //----------------------GET 請求方式 end -------------------------------- //----------------------POST 請求方式 start -------------------------------- /** * POST,Field,FieldMap,FormUrlEncoded(POST 方式請求有參數的時候必定不要忘記了這個註解) */ /** * post使用@Query註解進行參數傳遞 * * @param username * @param password * @return */ @FormUrlEncoded @POST("demo") Call<SampleResponse> postFun(@Field("username") String username, @Field("password") String password); /** * POST使用@FiledMap Map集合進行參數傳遞 * * @param params * @return */ @FormUrlEncoded @POST("demo") Call<SampleResponse> postFun(@FieldMap Map<String, Object> params); //----------------------POST 請求方式 end -------------------------------- //----------------------head參數加入start -------------------------------- /** * Headers。Header,HeaderMap * */ /** * 有些接口需要傳送一些操做client系統的信息,比方系統類型。系統版本號等例如如下 * * @param username * @param password * @return */ @Headers( {"os:Android" , "osversion:5.0" }) @FormUrlEncoded @POST("demo") Call<SampleResponse> postFunWithHead(@Field("username") String username, @Field("password") String password); /** * 有些接口需要傳送一些操做client系統的信息,比方系統類型。系統版本號等例如如下 * * @param username * @param password * @return */ @FormUrlEncoded @POST("demo") Call<SampleResponse> postFunWithHead(@Header("os") String os, @Header("osversion") String osversion, @Field("username") String username, @Field("password") String password); /** * 有些接口需要傳送一些操做client系統的信息,比方系統類型,系統版本號等例如如下 * * @param headParams head 參數。鍵值對的形式存儲到map集合中去 * @param username * @param password * @return */ @FormUrlEncoded @POST("demo") Call<SampleResponse> postFunWithHead(@HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password); //----------------------head參數加入end -------------------------------- //----------------------path 註解 -------------------------------- /** * Path註解使用時在請求方式註解後面的URL設置一個佔位符,使用大括號包裹。

在方法形參類型前使用@Path("佔位符")。 */ @FormUrlEncoded @POST("{path}") Call<SampleResponse> postFunWithHead(@Path("path") String path, @HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password); }

Activity代碼

public class SampleActivity extends AppCompatActivity { EditText etName; EditText etPassword; TextView tvResult; SampleApi sampleApi; SampleCallBack callback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample); etName = (EditText) findViewById(R.id.et_name); etPassword = (EditText) findViewById(R.id.et_password); tvResult = (TextView) findViewById(R.id.tv_result); //使用鏈式調用創建 sampleApi = new Retrofit .Builder() .baseUrl("http://10.0.2.2:8080/") .addConverterFactory(GsonConverterFactory.create()) .build() .create(SampleApi.class); callback = new SampleCallBack(); } /** * button點擊事件 * * @param view */ public void submit(View view) { tvResult.setText("正在請求...."); String name = etName.getText().toString(); String password = etPassword.getText().toString(); if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) { Toast.makeText(this, "參數不能爲空", Toast.LENGTH_SHORT).show(); return; } Call<SampleResponse> call; switch (view.getId()) { case R.id.btn_get: call = sampleApi.getFun(name, password); call.enqueue(callback); break; case R.id.btn_post: call = sampleApi.postFun(name, password); call.enqueue(callback); break; case R.id.btn_head: // call = sampleApi.postFunWithHead(name, password);//第一種,直接靜態定義方式。看接口方法 // call = sampleApi.postFunWithHead("ios","10.10.10",name, password);//另一種,可以動態配置值得方式 Map<String, String> map = new HashMap<>(); map.put("os", "android"); map.put("osversion", "9.9.9999999"); // call = sampleApi.postFunWithHead(map, name, password);//第三種,可以動態配置參數和值得形式 call = sampleApi.postFunWithHead("demo",map, name, password);//第四種,結合Path定義路徑 call.enqueue(callback); break; } } /** * @param result * 顯示結果 */ public void showResult(String result) { tvResult.setText(result); } /** * 回調實現類 */ public class SampleCallBack implements Callback<SampleResponse> { @Override public void onResponse(Call<SampleResponse> call, Response<SampleResponse> response) { //推斷網絡請求是否成功。網絡請求返回code爲[200..300)那麼與後臺鏈接成功。不然鏈接失敗 if (response.isSuccessful()) { //直接拿到JavaBean SampleResponse sampleResponse = response.body(); //這裏直接可以進行UI操做。OKHttp是不行的哦 showResult(sampleResponse.toString()); } else { //請求失敗。

假設代碼執行到這裏來講明是有跟後臺握手的,是後臺處理有問題,如404(沒有資源),500(後臺報錯了) showResult("查詢失敗。! -->code=" + response.code()); } } @Override public void onFailure(Call<SampleResponse> call, Throwable t) { //請求失敗。如。沒有聲明網絡權限、沒有網絡、或者是Retrofit 異常內部處理異常(如Gson解析失敗)也是會到這裏 t.printStackTrace(); showResult("查詢失敗:" + t.getCause()); } } }

執行效果

這裏寫圖片描寫敘述

4.URL操做注意事項

拼接注意,建議baseUrl用「/」結尾。接口中請求方式後面的url不用」/」開頭

樣例:baseUrl=http://10.0.2.2:8080/market/ url=home

錯誤案例

案例一:
baseUrl=http://10.0.2.2:8080/market url=home
—>http://10.0.2.2:8080/home
分析:默認用最後一個斜線去拼接

案例二:
baseUrl=http://10.0.2.2:8080/market url=/home
—>http://10.0.2.2:8080/home
分析:url中開始的斜線表明主機地址http://10.0.2.2:8080

源碼下載

Retrofit還可以實現上傳下載以及 結合RxJava使用,等下回分解!

相關文章
相關標籤/搜索