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類明顯不是一個有效的實體類,自然轉換失敗.
-------------------------------------------------------------------------------------------------------------官網教程
官方教程看起來有點亂,就直接看下面的常用操作吧
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
實作。
call.enqueue
call.execute
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後面自帶" ",這種寫法剛好可以符合下面的正确格式
-------------------------------------------------------------------------------------------------------------我的代碼
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/