Android 網絡框架 Retrofit2

概述

Retrofit是一個OkHttp網絡請求框架的封裝庫,Retrofit經過註解配置網絡參數,能夠按照咱們的規則去構造實際的HTTP請求,可以靈活設置URL、頭部、請求體、返回值等,是目前最優雅的一個網絡框架。html

添加依賴

implementation 'com.squareup.retrofit2:retrofit:2.2.0'

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'//添加對RxJava的支持
implementation 'com.squareup.retrofit2:converter-gson:2.1.0' //添加Json數據的支持

<uses-permission android:name="android.permission.INTERNET"/>//網絡請求必要的權限

Retrofit基本使用三部曲

建立實例

 Retrofit retrofit = new Retrofit.Builder()
          .baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必須以 /(斜線) 結束
          .build();
RetrofitService service = retrofit.create(RetrofitService.class);//建立接口的代理對象

定義接口

public interface RetrofitService {
    
    @GET("/pursuit/getPursuitInfo")
    Call<ResponseBody> getBlog(@Query("id") int id);

    @GET("/pursuit/getPursuitInfo/{id}")
    Call<ResponseBody> getBlog2(@Path("id") String id);
    
}

建立 同步/異步 回調 

//異步的回調
Call<ResponseBody> call = service.getBlog(123);
call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
        try {
            Log.i("返回信息",response.body().string()+"");//打印返回信息
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        t.printStackTrace();//錯誤信息
    }
});

/*同步的回調,若是不是在一個Activity或者一個Fragment中去執行,那麼也就意味着,你能夠不須要開啓子線程去執行網絡請求。若是是在主線程,就必須開啓子線程來進行同步請求
使用call.execute()同步請求,只能調用一次。若是要屢次使用這個方法,須要 call.clone()從新生成新的Call實例*/

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            retrofit2.Response<ResponseBody> response = call.execute();
            response.body();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
});

HTTP協議中的經常使用請求

GET: 請求指定的頁面信息,以?分割URL和傳輸數據,參數之間以&相連,最多隻能是1024字節,並返回實體主體,該操做用於獲取信息而非修改信息java

HEAD: 只請求頁面的首部。react

POST: POST表示可能修改變服務器上的資源的請求,.POST的安全性要比GET的安全性高android

PUT: 從客戶端向服務器傳送的數據取代指定文檔的內容。web

Retrofit註解的重點詳解

註解彙總

須要理解並靈活搭配使用json

基本請求

Responsebody是Retrofit網絡請求回來的原始數據類。get方式能夠在url後面串聯api

@Path註解用於替換請求參數,@Query註解至關於url後面的串聯,他們能夠同時使用安全

請看下面第三種表達式:服務器

@GET("/pursuit/getPursuitInfo?id=123")
Call<ResponseBody>  getCall();

@POST("/pursuit/getPursuitInfo")
Call<ResponseBody> getBlog(@Query("id") int id);

@GET("/pursuit/getPursuitInfo/{id}")
Call<ResponseBody> getBlog2(@Path("id") String id);

自定義請求

須要用到@HTTP註解網絡

/* method:網絡請求的方法,注意大小寫
 * path:網絡請求地址路徑
 * hasBody:是否有請求體
 * {id} 表示是一個變量*/
@HTTP(method = "GET", path = "/pursuit/getPursuitInfo/{id}", hasBody = false)
Call<ResponseBody> getCall(@Path("id") int id);

請求體非Form表單

@Body是Post方式提交非Form的表單

@POST("/pursuit/getPursuitInfo")
Observable<String> getPursuitInfo(@Body User user);

請求體是Form表單

若是請求的Form表單,須要用@FormUrlEncoded標註,@Field註解用於表單字段,它和@FieldMap都須要@FormUrlEncoded配合使用

@Field和@Query都是表單字段,@FieldMap和@Query都是批量增長表單的提交域。區別如上圖,一個拼接在URL上適用於get方式,一個體如今請求體上試用於post方式,區分好使用場景。

@POST("/pursuit/getPursuitInfo") 
@FormUrlEncoded
Call
<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

設置請求頭

兩種請求頭的,@Header用於添加不固定的請求頭,做用於方法的參數。@Headers用於添加固定的請求頭,做用於方法

@Headers("Authorization: authorization")
@GET("/pursuit/getPursuitInfo")
Call<ResponseBody> getUser();

@GET("/pursuit/getPursuitInfo")
Call<ResponseBody> getUser(@Header("Authorization") String authorization);

動態替換URL

用@Url替換已經設置的baseUrl

@GET
public Call<ResponseBody> profilePicture(@Url String url);

圖片上傳

@POST("user/updateAvatar.do")
@Multipart
Call<ResponseBody> upload(@Part("upload1\"; filename=\"image1.jpg\"") RequestBody imgs );

文件上傳

發送form-encoded的數據,用於有文件上傳的場景時要用 @Multipart 註解,@Part和@PartMap適用於有文件上傳的狀況

@POST("mobile/upload")
@Multipart
Call<ResponseBody> upload(@Part MultipartBody.Part file);

文件上傳相關閱讀

 輕鬆實現多文件/圖片上傳/Json字符串/表單

 Retrofit上傳文件的參數設置

※以上就是全部參數註解的用法,須要實踐靈活試用。

Retrofit與Gson

添加對gson的支持

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必須以 /(斜線) 結束
        .addConverterFactory(GsonConverterFactory.create())//添加對gson的支持
        .build();

創建接口,返回Bean

public interface PostRoute {
   @Headers({"Content-Type: application/json","Accept: application/json"})//須要添加頭
   @POST("api/FlyRoute/Add")
   Call<FlyRouteBean> postFlyRoute(@Body RequestBody route);//傳入的參數爲RequestBody
}

將Bean轉換成json字符串

FlyRouteBean flyRouteBean=new FlyRouteBean();
        flyRouteBean=initdata(flyRouteBean);//根據Bean類初始化一個須要提交的數據類
        Gson gson=new Gson();
        String route= gson.toJson(flyRouteBean);//經過Gson將Bean轉化爲Json字符串形式 

提交json數據

RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),route); //將json轉換成RequestBody請求體
Call<FlyRouteBean> call=postRoute.postFlyRoute(body);//提交

Retrifit與RxJava

引入RxJava

compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

 添加對RxJava的支持

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://id1.option****.cc:***1/")//Retrofit2 的baseUlr 必須以 /(斜線) 結束
        .addConverterFactory(GsonConverterFactory.create())//添加對gson的支持                                       
        .client(client)//添加okhttp的支持
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加對RxJava的支持
        .build();

鏈接超時與開啓okhttp的日誌打印

    private static final OkHttpClient client = new OkHttpClient.Builder().
            addInterceptor(new HttpLoggingInterceptor().//開啓日誌信息
            setLevel(HttpLoggingInterceptor.Level.BODY)).
            connectTimeout(600, TimeUnit.SECONDS).//鏈接超時
            readTimeout(600, TimeUnit.SECONDS).//讀取超時
            writeTimeout(600, TimeUnit.SECONDS).build();//寫入超時

創建接口,返回Observable被觀察者

@GET("top250")
Observable<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count);

創建觀察者

Observable<String> observable =service.getTopMovie(0, 10)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<ResponseBody>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(ResponseBody responseBody) {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });

Retrofit的簡單封裝

retrofit工具類

public class WebManager {
    private static WebManager webManager;
    private RetrofitService retrofitService;
    public WebManager(Context context) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(StaticConstant.HOST_PORT)//地址
                .addConverterFactory(GsonConverterFactory.create())//添加gson支持
                .client(client)//設置okhttp鏈接
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加RxJava的支持
                .build();
        retrofitService = retrofit.create(RetrofitService.class);
    }
    private static final OkHttpClient client = new OkHttpClient.Builder().
            addInterceptor(new HttpLoggingInterceptor().//開啓日誌信息
            setLevel(HttpLoggingInterceptor.Level.BODY)).
            connectTimeout(600, TimeUnit.SECONDS).//鏈接超時
            readTimeout(600, TimeUnit.SECONDS).//讀取超時
            writeTimeout(600, TimeUnit.SECONDS).build();//寫入超時
    //獲取單例
    public static WebManager getInstance(Context context){
        if(webManager == null){
            webManager = new WebManager(context);
        }
        return webManager;
    }
    //上傳xx信息,使用@Field註解
    public void postInfoField(Callback<ResponseBody> callback, String str){
        retrofitService.getWarrant("queryApplicationForm",null,str)
                .enqueue(callback);
    }
    //上傳xx信息,使用@FieldMap註解
    public void postInfoFieldMap(Callback<ResponseBody> callback, String num,String name){
        Map<String, Object> map=new HashMap<>();
        map.put("hotelCode",num);
        map.put("hotelName",name);
        retrofitService.getUnlicensedNum(map).enqueue(callback);
    }
    //上傳xx信息,使用@Body 註解
    public void postMultipartBody(Callback<ResponseBody> callback, String key,File file, String name){
        MultipartBody.Builder builder=  new MultipartBody.Builder().setType(MultipartBody.FORM);
        if(file.exists()) {
            builder.addFormDataPart("access_token", key);
            builder.addFormDataPart("name", name);
            builder.addFormDataPart("image", ImageUtil.imageToBase64(file.getPath()));
            builder.addFormDataPart("image_type", "BASE64");
        }
        retrofitService.getUnlicensedCheck(builder.build()).enqueue(callback);
    }
    //上傳xx信息,帶文件,使用@Body 註解
    public void postMultipartBody2(Callback<ResponseBody> callback, HotelInfo hotelInfo,String pictureCardPath,String picturePath){
        Gson gson=new Gson();
        String json= gson.toJson(hotelInfo);
        File file = new File(pictureCardPath);
        File file2 = new File(picturePath);
        MultipartBody.Builder builder=  new MultipartBody.Builder().setType(MultipartBody.FORM);
        if(!file.exists()&&!file2.exists()) {
            try {
                builder.addFormDataPart("info", json);
                builder.addFormDataPart("file",file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
                builder.addFormDataPart("file2",file2.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file2));
                retrofitService.getHotelInfoFile(builder.build()).enqueue(callback);
            } catch (Exception e) {
                e.printStackTrace();
                Log.i("WebManager","上傳異常");
            }
        }
    }
    
}

retrofit服務類

public interface RetrofitService {
    @FormUrlEncoded
    @POST("/Hotels/ExpressServlet")
    Call<ResponseBody> getWarrant(@Field("type") String type, @Field("E_Code") String code, 
    @Field("applicationFormId") String id);

    @FormUrlEncoded
    @POST("Hotels/NoRegisterServlet")
    Call<ResponseBody> getUnlicensedNum(@FieldMap Map<String,Object> fieldMap);

    @POST("/rest/2.0/face/v3/person/verify")
    Call<ResponseBody> getUnlicensedCheck(@Body MultipartBody builder);

    @Headers("Connection: close" )
    @POST("/Hotels/UploadFileImgServlet")
    Call<ResponseBody> getHotelInfoFile(@Body MultipartBody builder);

}

 

RxJava相關閱讀

Android異步框架 RxJava

Retrofit代碼混淆配置

-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions
相關文章
相關標籤/搜索