Android開發 retrofit入門講解


前言

  retrofit基於okhttp封裝的網絡請求框架,網絡請求的工作本質上是 OkHttp 完成,而 retrofit 僅負責網絡請求接口的封裝.如果你不了解OKhttp建議你還是先了解它在來學習使用retrofit,傳送門:Android 開發 框架系列 OkHttp使用詳解

  Retrofit優勢,就是簡潔易用,解耦,擴展性強,可搭配多種Json解析框架(例如Gson),另外還支持RxJava.但是,這篇博客不講解RxJava配合使用的部分,與RxJava的配合使用將在另外一篇博客中講解.

  另外retrofit已經是封裝的非常好了,已經最大程度上的匹配各種使用情況,所以不建議多此一舉的再次封裝retrofit(最多封裝retrofit的單例). 再次封裝不會看起來很帥也不會讓你很牛逼. 只會讓你看起來更蠢.把已經很拓展很解耦的實現全部破壞.

Github地址

  https://github.com/square/retrofit

依賴

  如果你不需要使用RxJava模式,那么你只需要依賴下面2個:

    implementation 'com.squareup.retrofit2:retrofit:2.6.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

  gson是用來解析的Json數據使用的(個人偏愛Gson),retrofit也支持其他解析工具比如fastJson

簡單的Demo(異步請求)

  老規矩按思維順序講解demo

1.創建Retrofit請求基礎配置

  Retrofit配置好后,可以全局使用這一個Retrofit用來請求網絡(所以你可以實現單例以全局使用),當然下面的代碼只是demo:

 

  private Retrofit mRetrofit;
  private void initHttpBase(){
        mRetrofit = new Retrofit.Builder()
                .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的網絡地址  baseUrl不能為空,且強制要求必需以 / 斜杠結尾
                .addConverterFactory(GsonConverterFactory.create())//使用Gson解析
          .callbackExecutor(Executors.newSingleThreadExecutor())//使用單獨的線程處理 (這很重要,一般網絡請求如果不設置可能不會報錯,但是如果是下載文件就會報錯)
                .build();
    } 

注意! base的網絡地址 baseUrl不能為空,且強制要求必需以 / 斜杠結尾

2.創建數據返回后的Bean類

public class LoginBean {
    private int code;
    private String message;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2.創建一個網絡請求接口

public interface HttpList {

    @FormUrlEncoded //注解表示from表單  還有@Multipart 表單可供使用 當然你也可以不添加
    @POST("test/login_test") //網絡請求路徑
    Call<LoginBean> login(@Field("number") String number, @Field("password") String password); //@Field("number") 為post值的的key

}

注意,這是一個接口類. LoginBean則是數據返回后的Bean類(Retrofit會自動使用導入的Gson解析)

注意! @POST("test/login_test") 這路徑最前面不能加斜杠 /  ,否則它會自動裁剪路徑,這樣會導致你的路徑錯誤

3.請求網絡

private void postHttp(){
        HttpList httpList = mRetrofit.create(HttpList.class);
        Call<LoginBean> call = httpList.login("181234123", "123456");
        call.enqueue(new Callback<LoginBean>() {
            @Override
            public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
                LoginBean bean = response.body();
                Log.e(TAG, "onResponse: code="+bean.getCode());
                Log.e(TAG, "onResponse: message="+bean.getMessage());
            }

            @Override
            public void onFailure(Call<LoginBean> call, Throwable t) {
                Log.e(TAG, "onFailure: 網絡請求失敗="+t.getMessage());

            }
        });
    }

 這樣,我們就完成了一個網絡請求.是不是特別簡單

同步請求

private void postHttp2() {
        HttpList httpList = mRetrofit.create(HttpList.class);
        final Call<LoginBean> call = httpList.login("181234123", "123456");
        new Thread(new Runnable() { //Android主線程不能操作網絡請求,所以new一個線程來操作
            @Override
            public void run() {
                try {
                    Response<LoginBean> response = call.execute();//同步請求網絡
                    LoginBean bean = response.body();
                    Log.e(TAG, "onResponse: code=" + bean.getCode());
                    Log.e(TAG, "onResponse: message=" + bean.getMessage());
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }

取消網絡請求

    public void cancelHttp(){
        HttpList httpList = mRetrofit.create(HttpList.class);
        //這里貼這部分代碼是告訴call是哪里來的,關鍵點就是這個call,當然你也可以從回調里獲取
        mCall = httpList.login("181234123", "123456");

        mCall.cancel(); //取消請求
    }

如何添加Header頭

以固定數據的形式添加頭信息

public interface HttpList {

    @Headers({"content1:one","content2:two"})
    @POST("test/logout_test")
    Call<LoginBean> logout1();

}

以非固定數據的形式添加頭信息

public interface HttpList {

    @POST("test/logout_test")
    Call<LoginBean> logout2(@Header("content") String content);

}

Body配置

Body一般有4個種類

  • application/x-www-form-urlencoded 表單數據
  • multipart/form-data 表單文件上傳
  • application/json 序列化JSON數據
  • text/xml XML數據

框架直接提供的2個Body

public interface HttpList {

    @FormUrlEncoded //application/x-www-form-urlencoded  表單body
    @POST("test/login_test") 
    Call<LoginBean> login2(@Field("number") String number, @Field("password") String password);


    @Multipart //multipart/form-data  此body支持文件上傳與下載
    @POST("test/login_test") 
    Call<LoginBean> login3(@Field("number") String number, @Field("password") String password);


}

自定義Body

其他2個就需要自定義創建了,下面舉例Json Body的創建:

  /**
     *
     * @param string  直接導入需要發送給服務器的JSON的String值
     * @return
     */
    public static RequestBody getRequestBody(String string) {
        return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), string);
    }

在接口類參數需要設置為 @Body RequestBody requestBody

    @POST("app/system/demo")
    Observable<UpdateInfo> demo(@Body RequestBody requestBody);

添加配置的OkHttpClient(主要使用請求超時/攔截器等功能)

上面說了retrofit是基於Okhttp開發的網絡請求框架,所以它有一部分的功能依然需要使用Okhttp的方式來配置比如請求超時時間/設置攔截器等等,下面就展示一下如何添加

    private void initHttpBase2() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(false) //在連接失敗時重試
                .callTimeout(30, TimeUnit.SECONDS) //呼叫超時,設置此參數為整體流程請求的超時時間
                .connectTimeout(20,TimeUnit.SECONDS)//連接超時
                .readTimeout(20,TimeUnit.SECONDS)//讀取超時
                .writeTimeout(20,TimeUnit.SECONDS)//寫入超時
//                .callTimeout()//呼叫超時,設置此參數為整體流程請求的超時時間
//                .addInterceptor() //設置攔截器
//                .authenticator() //設置認證器
//                .proxy()//設置代理
                .build();

        mRetrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://doclever.cn:8090/mock/5c3c6da33dce46264b24452b/")//base的網絡地址
                .addConverterFactory(GsonConverterFactory.create())//使用Gson解析
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
    }

部分路徑動態的BaseUrl

    @POST("/article/query/{page}/json")
    @FormUrlEncoded
    Observable<DataResponse<Article>> getSearchArticles(@Path("page") int page, @Field("k") String k);

實現Url路徑傳參數

@Query 有值的查詢名稱

    @GET("app/data")
    Call<Result> getData(@Query("id") String id);
    @GET("app/data")
    Call<Result> getData(@Query("id") String... id);

@QueryName 只有值沒有key的傳參

    @GET("app/data")
    Call<Resul> getData(@QueryName String id);
    @GET("app/data")
    Call<Resul> getData(@QueryName String... id);

@QueryMap 用哈希集合傳值

    @GET("app/data")
    Call<Result> getData(@QueryMap Map<String,String> map);

 

end


免責聲明!

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



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