Retrofit網絡框架入門使用


1.簡單介紹

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

我們僅僅須要通過簡單的配置就能使用retrofit來進行網絡請求了。

Retrofit能夠直接返回Bean對象,比如假設我們進行一個網絡接口的請求。返回來一串json字符串。那么這個時候一般我們都要拿到這個json字符串后進行解析得到相應的Bean對象,Retrofit僅僅要依賴一下Gson的轉換庫然后進行簡單的配置就能夠直接拿到Bean對象了,不須要我們自己去解析。

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

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

這里寫圖片描寫敘述

看了這個圖之后你有什么想法?

Talk is cheap, show me the code!

2.高速使用

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

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

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

{"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使用,等下回分解!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM