天天看點

Android retrofit2基本操作

retrofit底層實作是okhttp

retrofit就是對okhttp做了一層封裝。把網絡請求都交給給了Okhttp,我們隻需要通過簡單的配置就能使用retrofit來進行網絡請求了。Retrofit架構存在的優勢:

① Retrofit使用注解方式,大大簡化了我們的URL拼寫形式,而且注解含義一目了然,簡單易懂;

② Retrofit使用簡單,結構層次分明,每一步都能清晰的表達出之是以要使用的寓意;

③ Retrofit支援同步和異步執行,使得請求變得異常簡單,隻要調用enqueue/execute即可完成;

④ Retrofit更大自由度的支援我們自定義的業務邏輯,如自定義Converters。

⑤ Retrofit支援多種檔案解析(Gson,Json,XML,Protobuf)

⑥ Retrofit支援RxJava

P.s.注意點

retrofit預設轉換string成json obj,如果不需要gson轉換,那麼就指定泛型為ResponseBody,不要設定gson轉換器

 *  隻能是ResponseBody,子類都不行,同理,下載下傳上傳時,也必須指定泛型為ResponseBody

response.body().string() 調用一次,就釋放資源(也就是隻能調用一次)

https://blog.csdn.net/my_truelove/article/details/78998996

示例

public interface ZhailuData1 {
    @GET("api/v1/{id}")
    Call<ResponseBody> getZhailuData(@Path("id") String  index);
}

//而不能是:
 @GET()
Call<String> getZhailuData(@Path("id") String  index);


//如果這樣指定,意思是,使用retrofit内部的json轉換器,将response裡的資料轉換成一個實體類xxx,比如UserBean之類的,而String類明顯不是一個有效的實體類,自然轉換失敗.

           
Android retrofit2基本操作

-------------------------------------------------------------------------------------------------------------官網教程

官方教程看起來有點亂,就直接看下面的常用操作吧

https://square.github.io/retrofit/

-------------------------------------------------------------------------------------------------------------常用操作

常用操作:

http://192.168.1.102:8080/springmvc_users/user/users

http://192.168.1.102:8080/springmvc_users/user/zhy

http://192.168.1.102:8080/springmvc_users/user/lmj

http://baseurl/users?sortby=username

http://baseurl/users?sortby=id

最基本的get請求:

public interface IUserBiz
{
    @GET("users")
    Call<List<User>> getUsers();
}

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://192.168.31.242:8080/springmvc_users/user/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
IUserBiz userBiz = retrofit.create(IUserBiz.class);
Call<List<User>> call = userBiz.getUsers();
        call.enqueue(new Callback<List<User>>()
        {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response)
            {
                Log.e(TAG, response.body() + "");
            }
            @Override
            public void onFailure(Call<List<User>> call, Throwable t)
            {
                Log.e(TAG, "請求失敗或其他錯誤");
            }
        });
           

1.      接口中的方法必須有傳回值,且比如是Call<T>類型

2.      .addConverterFactory(GsonConverterFactory.create())這裡如果使用gson,需要額外導入:

compile 'com.squareup.retrofit2:converter-gson:2.0.2'

3.      既然

call.enqueue

是異步的通路資料,那麼同步的通路方式為

call.execute

,這一點非常類似okhttp的API,實際上預設情況下内部也是通過

okhttp3.Call

實作。

Path和Query用法:

public interface IUserBiz
{
    @GET("{username}")
    Call<User> getUser(@Path("username") String username);
}
Call<User> call = userBiz.getUser("zhy");


public interface IUserBiz
{
    @GET("users")
    Call<List<User>> getUsersBySort(@Query("sortby") String sort);
}
Call<List<User>> call = userBiz.getUsersBySort("username");
           

Post和Body和Field用法: 

public interface IUserBiz
{
 @POST("add")
 Call<List<User>> addUser(@Body User user);
}
Call<List<User>> call = userBiz.addUser(new User(1001, "jj", "123,", "jj123", "[email protected]"));


public interface IUserBiz
{
    @POST("login")
    @FormUrlEncoded
    Call<User> login(@Field("username") String username, @Field("password") String password);
}
Call<User> call = userBiz.login("zhy", "123");
           

Multipart+Part用法 

public interface IUserBiz
{
    @Multipart
    @POST("register")
    Call<User> registerUser(@Part MultipartBody.Part photo, @Part("username") RequestBody username, @Part("password") RequestBody password);
}

File file = new File(Environment.getExternalStorageDirectory(), "icon.png");
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("photos", "icon.png", photoRequestBody);
Call<User> call = userBiz.registerUser(photo, RequestBody.create(null, "abc"), RequestBody.create(null, "123"));
           

PartMap用法

public interface IUserBiz
 {
     @Multipart
     @POST("register")
     Call<User> registerUser(@PartMap Map<String, RequestBody> params,  @Part("password") RequestBody password);
}

File file = new File(Environment.getExternalStorageDirectory(), "messenger_01.png");
RequestBody photo = RequestBody.create(MediaType.parse("image/png", file);
Map<String,RequestBody> photos = new HashMap<>();
photos.put("photos\"; filename=\"icon.png", photo);
photos.put("username",  RequestBody.create(null, "abc"));
Call<User> call = userBiz.registerUser(photos, RequestBody.create(null, "123"));
           

關于這裡為什麼是這樣的"photos\"; filename=\"icon.png"

因為name後面自帶" ",這種寫法剛好可以符合下面的正确格式

Android retrofit2基本操作

-------------------------------------------------------------------------------------------------------------我的代碼

Post+Field(不要忘了@FormUrlEncoded參數,否則用不了)

//retrofit2的一個post接口
public interface SignUpPost {
        //test1
        @FormUrlEncoded
        @POST("register")
        Call<ResponseBody> postData(@Field("telephone") String telephone,@Field("code") String code,@Field("password") String password);
}

//retrofit擷取資料Data2,之後gson解析到Result成員變量中
    public void retrofitV1() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("http://test.com/api/Login/")
                        .build();
                SignUpPost signUpPost=retrofit.create(SignUpPost.class);
                Call<ResponseBody> call=signUpPost.postData("18668197127","7900","Zsxcfv123456");
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            responseString=response.body().string();
                            Log.i(TAG, "onResponse測試: "+responseString);

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Log.i(TAG, "onResponse: "+t.toString());
                    }
                });
            }
        }).start();
    }
           

FormUrlEncoded注解:

用于修飾Field注解和FieldMap注解

使用該注解,表示請求正文将使用表單網址編碼。字段應該聲明為參數,并用@Field注釋或FieldMap注釋。使用FormUrlEncoded注解的請求将具”application / x-www-form-urlencoded” MIME類型。字段名稱和值将先進行UTF-8進行編碼,再根據RFC-3986進行URI編碼.

Post+Body(記得要設定Gson轉換器才能用)

//retrofit2的一個post接口
public interface SignUpPost {

        @POST("register")
        Call<ResponseBody> postData2(@Body RegisterData registerData);
}

public class RegisterData {
    private String telephone;
    private String code;
    private String password;

    public RegisterData(String telephone, String code, String password) {
        this.telephone = telephone;
        this.code = code;
        this.password = password;
    }

    //set和get方法省略
}
Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("http://test.mouqukeji.com/api/Login/")
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
SignUpPost signUpPost=retrofit.create(SignUpPost.class);
Call<ResponseBody> call=signUpPost.postData2(new RegisterData("18668197127","1941","Zsxcfv123456"));
           

-------------------------------------------------------------------------------------------------------------參考

記錄我自己開發中的一個小錯誤:

我第一次用retrofit的時候以為隻是簡單的網絡請求架構,每次在使用過程中手動開起子線程new Thread,然後把retrofit執行個體放在run()裡面調用.

現在發現retrofit的請求已經封裝了線程操作,我之前相當于畫蛇添足,在子線程裡面套了線程

參考:

https://juejin.im/entry/57ce31b22e958a0054386d87

https://www.jianshu.com/p/308f3c54abdd

https://blog.csdn.net/lmj623565791/article/details/51304204

https://square.github.io/retrofit/

繼續閱讀