1. 程式人生 > >Retrofit 2.0基於OKHttp更高效更快的網絡框架 以及自定義轉換器

Retrofit 2.0基於OKHttp更高效更快的網絡框架 以及自定義轉換器

讀取數據 index gson final resp adapter oid 簡單的 build

時間關系,本文就 Retrofit 2.0的簡單使用 做講解 至於原理以後有空再去分析

項目全面、簡單、易懂 地址:

關於Retrofit 2.0的簡單使用如下: https://gitee.com/bimingcong/MyRetrofit

private void initGet() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://v.juhe.cn/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        GetService service 
= retrofit.create(GetService.class); final Call<GetBean> call = service.getString3("toutiao", "shehui", "d05b58fa6901ad9bed77a1ef08bd6ccb"); call.enqueue(new Callback<GetBean>() { @Override public void onResponse(Call<GetBean> call, Response<GetBean> response) {
if (response.isSuccessful()) { GetBean = response.body(); } } @Override public void onFailure(Call<GetBean> call, Throwable t) { } }); }

其中的GetService是幹嘛的 裏邊的@query其實可以理解為get請求url ?後邊那一串參數的鍵值對

public interface GetService {
    //直接拼接,記得加問號
    @GET("toutiao/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
    Call<GetBean> getString();

    //{name}可以最簡單的將其理解為路徑替換塊,用”{}”表示,與註解@path配合使用 ,為了解耦,參數name==toutiao
    @GET("{name}/index?type=shehui&key=d05b58fa6901ad9bed77a1ef08bd6ccb")
    Call<GetBean> getString2(@Path("name") String name);

    //對於@GET來說,參數信息是可以直接放在url中上傳的。那麽你馬上就反應過來了,這一樣也存在嚴重的耦合!
    //於是,就有了@query
    @GET("{name}/index")
    Call<GetBean> getString3(@Path("name") String name, @Query("type") String type
            , @Query("key") String key);

    //假設我要在參數中上傳10個參數呢?這意味著我要在方法中聲明10個@Query參數?當然不是!
    //Retrofit也考慮到了這點,所以針對於復雜的參數上傳,為我們準備了@QueryMap
    @GET("{name}/index")
    Call<GetBean> getString4(@Path("name") String name, @QueryMap HashMap<String, String> hashMap);

    //一般Get都沒有請求體,所以直接獲取接口網址即可 Url動態化
    @GET()
    Observable<ResponseBody> getString5(@Url String url);

}

針對Post請求 其中的@Field 其實可以理解為 post要提交的 參數鍵值對 其中還有單個文件 以及多個文件的上傳

public interface PostService {
    @FormUrlEncoded
    @POST("toutiao/index")
    Call<PostBean> postString(@Field("type") String type, @Field("key") String key);

    // Post表單提交-多個參數-@FieldMa
    @FormUrlEncoded
    @POST("toutiao/index")
    Call<PostBean> postString2(@FieldMap HashMap<String, String> params);

    // Post文件提交 ,每個鍵值對都需要用@Part註解鍵名字
    //Multipart 支持文件上傳
    @Multipart
    @POST("https://pan.baidu.com/disk/home?#/all?vmode=list&path=%2Fas")
    Call<TestBean> postFile(@Part("photo\";filename=\"test.png\"") RequestBody body);

    @Multipart
    @POST("xxxx")
    Call<TestBean> postFile2(@PartMap HashMap<String, RequestBody> bodyMap, @Field("token") String token);


}

對應的例子如下:

//當我獲取數據成功後要做什麽處理
    public interface OnSuccessListener {
        void onSuccess(Object o);

        void onFaile();
    }

 //提供一些方法去調用service實體類的方法,RequestBody上傳單個文件
    public void uploadFile(RequestBody body, final OnSuccessListener listener) {
        Call<TestBean> call = mService.postFile(body);
        call.enqueue(new Callback<TestBean>() {
            @Override
            public void onResponse(Call<TestBean> call, Response<TestBean> response) {
                listener.onSuccess(response);
            }

            @Override
            public void onFailure(Call<TestBean> call, Throwable t) {
                listener.onFaile();
            }
        });

    }

轉換器:

至於自定義轉換器 就是 下邊這個參數

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://v.juhe.cn/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

比如我們只希望返回數據是String類型,我們需要自定義一個ConverterFactory

public class StringConverFactory extends Converter.Factory {
    public static StringConverFactory create() {
        return new StringConverFactory();
    }
 
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        Log.d("wyz", "讀取數據:responseBodyConverter" + type);
        if (type == String.class) {//此處的Type類型 我的理解是一開始Call對象參數定義的返回值類型
            Log.d("wyz", "執行開始");
            return StringResponseBodyConverter.INSTANCE;
        }
        return null;
    }
 
    @Nullable
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        Log.d("wyz", "請求數據類型:" + type);
        if (type == NetRequest.class){
 
        }
        return null;
    }
final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
    public static final StringResponseBodyConverter INSTANCE =new StringResponseBodyConverter();
    @Override
    public String convert(ResponseBody value) throws IOException {
        Log.d("wyz", "轉換開始:" + value);
        String s = value.string();
        return s;
    }

最後將 ConvertFactory設置到Retrofit實例中就可以了

retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(getOkHttpClient())
                .addConverterFactory(StringConverFactory.create())

日誌:

最後對於 紅色的部分是添加一個自定義的Client 此處主要是對相應級別的日誌去攔截

在retrofit2.0中是沒有日誌功能的。但是retrofit2.0中依賴OkHttp,所以也就能夠通過OkHttp中的interceptor來實現實際的底層的請求和響應日誌。在這裏我們需要修改上一個retrofit實例,為其自定自定義的OkHttpClient。代碼如下:

HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(httpLoggingInterceptor)
        .build();

Retrofit retrofit = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .client(okHttpClient)
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

需要添加依賴:

compile ‘com.squareup.okhttp3:logging-interceptor:3.1.2‘

效果:

技術分享圖片

更加詳細的Demo 可以去我的開源中國裏看 https://gitee.com/bimingcong/MyRetrofit

Retrofit 2.0基於OKHttp更高效更快的網絡框架 以及自定義轉換器