**版權(quán)聲明:本文為小斑馬偉原創(chuàng)文章徙歼,轉(zhuǎn)載請(qǐng)注明出處!
Retrofit:(A type-safe HTTP client for Android and Java)通過(guò)注解的方式描述HTTP請(qǐng)求,底層由OKHttp實(shí)現(xiàn) 看成是對(duì)OKHttp的一次封裝犁河,采用注解方式來(lái)描述HTTP請(qǐng)求。非常適合RESTFul風(fēng)格的網(wǎng)絡(luò)請(qǐng)求,目前版本2.0.0.
一魄梯、 RESTful
REST:是 “REpresentational State TRransfer” 的縮寫(xiě)桨螺,即"表現(xiàn)層狀態(tài)轉(zhuǎn)換"。表現(xiàn)層:網(wǎng)絡(luò)上資源的變現(xiàn)形式(資源:是網(wǎng)絡(luò)上的一個(gè)實(shí)體酿秸,或者說(shuō)網(wǎng)絡(luò)上的具體信息灭翔,可以是一段文本、一張圖片辣苏、一首歌曲肝箱、一種服務(wù)∠◇總之就是具體的實(shí)在煌张。我們可以用一個(gè)URI,統(tǒng)一定向符指向它退客。每種資源對(duì)應(yīng)一個(gè)特定的URI骏融,要獲取它的資源链嘀,就要訪問(wèn)它的URI。因此URI就成為每一個(gè)資源的地址档玻,或者獨(dú)一為二識(shí)別符怀泊。我們常說(shuō)的上網(wǎng)就是互聯(lián)網(wǎng)上的資源的互動(dòng),調(diào)用它的URI窃肠。表現(xiàn)層就是網(wǎng)絡(luò)資源的一種表現(xiàn)形式包个。資源是實(shí)體信息,它可以多種外在的形式冤留,我們把資源具體呈現(xiàn)出的信息碧囊,我們叫它表現(xiàn)層。比如文本可以用txt形式表現(xiàn)纤怒,也可以用html形式表現(xiàn)糯而。URI只代表資源的實(shí)體。不代表資源的形式泊窘。嚴(yán)格上來(lái)說(shuō)熄驼,某些文件的后綴名是可以不需要的,因?yàn)樗潜硎靖袷胶姹硎颈憩F(xiàn)層的范疇瓜贾。而URI只表示資源的位置。它的具體表現(xiàn)形式携悯,應(yīng)該在HTTP請(qǐng)求的頭部信息中祭芦,用Content-Type和Obser形式指定)。
狀態(tài)轉(zhuǎn)換:客戶端通過(guò)某種手段使得服務(wù)器上資源發(fā)生變化憔鬼,訪問(wèn)一個(gè)網(wǎng)站龟劲,肯定會(huì)涉及到客戶端和服務(wù)端互動(dòng)過(guò)程,在這個(gè)過(guò)程中轴或,勢(shì)必涉及到數(shù)據(jù)和狀態(tài)的轉(zhuǎn)換昌跌,互聯(lián)網(wǎng)的協(xié)議是HTTP狀態(tài)的協(xié)議,這就意味著所有的狀態(tài)必須保存在服務(wù)器端照雁,如果客戶端要操作數(shù)據(jù)蚕愤,就必須通過(guò)某種手段,讓服務(wù)器端發(fā)生狀態(tài)轉(zhuǎn)換饺蚊。而這種轉(zhuǎn)化是建立在表現(xiàn)層上的萍诱,所以就是表現(xiàn)層的狀態(tài)轉(zhuǎn)換。而客戶端使用的手段卸勺,只能是HTTP的協(xié)議,具體的說(shuō)就是HTPP里面具體四個(gè)操作符的動(dòng)詞烫扼,GET POST PATH DELETE曙求。
二、 RESRful架構(gòu)
- 1、每一個(gè)URI代表一種資源悟狱,而不是對(duì)資源的一種操作静浴。
- 2、客戶端和服務(wù)器之間挤渐,傳遞這種資源的某種表現(xiàn)層苹享。
- 3、客戶端通過(guò)HTTP動(dòng)作浴麻,對(duì)服務(wù)端資源進(jìn)行操作得问。
三、Retrofit引入
compile’com.squareup.retrofit2:retrofit:2.0.1'
四软免、Retrofit請(qǐng)求網(wǎng)絡(luò)流程*
定義一個(gè)URL:http://192.168.31.242:8080/android/user/users
-
3.1 定義一個(gè)接口對(duì)象
public interface IUserInfo { GET("users") Call<List<User>> getUsers(); }
-
3.2 構(gòu)造Retrofit對(duì)象
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://192.168.31.242:8080/android/user/") .addConverterFactory(GsonConverterFactory.create()) //json格式轉(zhuǎn)換器 .build();
-
3.3 拿到接口對(duì)象的實(shí)例
IUserInfo userInfo = retrofit.create(IUserInfo.class);
-
4.3由接口對(duì)象生成call對(duì)象宫纬,并執(zhí)行網(wǎng)絡(luò)請(qǐng)求
Call<List<User>> call = userInfo.getUsers(); call.enqueue(new Callback<List<User>>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { Log.i(TAG,"onResponse:"+response.body()+""); } @Override public void onFailuse(Call<List<User>>call, Throwable t){} });
五、Retrofit常用注解 - @Path
1.用于訪問(wèn)zhangsan的信息
http://192.168.1.102:8080/android/user/users/zhangsan
2.用于訪問(wèn)lisi的信息
http://192.168.1.102:8080/android/user/users/lisi
這種風(fēng)格URL只是符合RESTful的設(shè)計(jì)風(fēng)格的膏萧,URL只表示資源信息漓骚,因?yàn)槲覀冊(cè)谶@個(gè)URL看不到任何的網(wǎng)絡(luò)信息的請(qǐng)求。這個(gè)請(qǐng)求在我們的html方法中來(lái)執(zhí)行榛泛。這種的類型的API就是RESRful的API蝌蹂。
public interface IUserInfo {
@GET("{username}") //占位符 通過(guò)傳遞來(lái)到參數(shù)進(jìn)行替換
Call<User> getUser(@Path("username") String username);
}
//Call<User> call = userInfo.getUser("zhangsan")
Call<User> call = userInfo.getUser("lisi");
五、Retrofit常用注解 - @Query
1.用于訪問(wèn)zhangsan的信息
http://192.168.1.102:8080/android/user/users/?name=zhangsan
2.用于訪問(wèn)lisi的信息
http://192.168.1.102:8080/android/user/users/?name=lisi
public interface IUserInfo {
GET("users")
Call<List<User>> getUsersByName(@Query("name") String name); //定義一個(gè)key:name 后面?zhèn)鬟f來(lái)的參數(shù)曹锨。通過(guò)Query注解來(lái)拼接孤个,把key:name和后面?zhèn)鬟f來(lái)的name拼接成一個(gè)鍵值對(duì)。然后把這個(gè)鍵值對(duì)加到URL后面艘希。
}
//Call<List<User>> call = userInfo.getUserByName("zhangsan");
Call<List<User>> call = userInfo.getUserByName("lisi");
定義一個(gè)key:name 后面?zhèn)鬟f來(lái)的參數(shù)硼身。通過(guò)Query注解來(lái)拼接,把key:name和后面?zhèn)鬟f來(lái)的name拼接成一個(gè)鍵值對(duì)覆享。然后把這個(gè)鍵值對(duì)加到URL后面佳遂。
六、Retrofit常用注解 - @Body(一般用于POST)請(qǐng)求
public interface IUserInfo {
@POST("users")
Call<List<User>> addUser(@Body User user);
}
Call<User> call = userInfo.addUser(new User(236,"zhangsan")); //把一個(gè)json對(duì)象的字符串發(fā)送給服務(wù)器的
通過(guò)POST定義是一個(gè)POST請(qǐng)求撒顿,POST后面的請(qǐng)求的值和baseUrl組成一個(gè)完成的請(qǐng)求的URL的路徑丑罪,然后定義了一個(gè)方法addUser添加用戶,通過(guò)Body注解在調(diào)用這個(gè)方法的時(shí)候凤壁,只需要傳遞一個(gè)對(duì)象吩屹。這個(gè)注解自動(dòng)把這個(gè)對(duì)象轉(zhuǎn)換成json字符串。添加到我們網(wǎng)絡(luò)請(qǐng)求的Body中拧抖,發(fā)給服務(wù)器煤搜。定義這個(gè)接口后,如果我們添加一個(gè)張三唧席,通過(guò)userInfo事例的addUser方法擦盾,傳遞來(lái)一個(gè)User就OK嘲驾。
七、Retrofit常用注解 - @FormUrlEncoded 表示以表單的形式傳遞鍵值對(duì)迹卢。
public interface IUserInfo {
@POST("register")
@FormUrlEncoded
Call<User> register(@Field("userid") String userid, @Field("username") String username);
}
Call<User> call = userInfo.register("123","zhangsan"); //FormUrlEncoded注解自動(dòng)的將123和zhangsan 以及userid和username拼接成鍵值對(duì)的方式辽故,發(fā)送給服務(wù)器。
八腐碱、Retrofit常用注解 - @Multipart (表示單文件上傳)
public interface IUserInfo {
@Multipart //多個(gè)Part
@POST("register")
Call<User> register(@Part MultipartBody.Part icon, @Part("userid") RequestBody userid); //1.part 表示上傳的文件誊垢,第二個(gè)part表示是一個(gè)鍵值對(duì),表示用戶的ID
}
發(fā)起GET請(qǐng)求
private void getRequest() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
IGetInfos getInfos = retrofit.create(IGetInfos.class);
Call<ResponseCategory> call = getInfos.getCategories();
call.enqueue(new Callback<ResponseCategory>() {
@Override
public void onResponse(Call<ResponseCategory> call, Response<ResponseCategory> response) {
ResponseCategory responseCategory = response.body();
Log.i("data","onResponse() success !!");
}
@Override
public void onFailure(Call<ResponseCategory> call, Throwable t) {
}
});
}
private String baseUrl = "http://35.185.149.228";
private class ResponseCategory {
public int status;
public List<CategoryMode> date;
public class CategoryMode {
public int id;
public String name;
}
}
private interface IGetInfos {
@GET("user/get-big-direction")
Call<ResponseCategory> getCategories();
}
發(fā)起POST上傳鍵值對(duì)(登錄)
private void postPairs() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
IUserLogin userLogin = retrofit.create(IUserLogin.class);
Call<RespLoginModel> call = userLogin.login("sda","233");
call.enqueue(new Callback<RespLoginModel>() {
@Override
public void onResponse(Call<RespLoginModel> call, Response<RespLoginModel> response) {
RespLoginModel responseCategory = response.body();
Log.i("data","onResponse() success !!");
}
@Override
public void onFailure(Call<RespLoginModel> call, Throwable t) {
}
});
}
public class RespLoginModel {
public int status;
public User data;
public class User {
private String id;
private String username;
private String avatar;
}
}
public interface IUserLogin{
@POST("user/do-login")
@FormUrlEncoded
Call<RespLoginModel> login(@Field("login-username") String username,@Field("login-password") String password);
}
上傳文件
private void upLoad() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
IUpLoadIcon upLoadIcon = retrofit.create(IUpLoadIcon.class);
File file = new File(Environment.getExternalStorageDirectory()+"ic_laucher.png");
RequestBody photoBody = RequestBody.create(MediaType.parse("imge/png"),file);
MultipartBody.Part phone = MultipartBody.Part.createFormData("uplaodImg[file]",file.getName(),photoBody);
Call<RespUpLoadModel> call = upLoadIcon.upLoadIcon(phone);
call.enqueue(new Callback<RespUpLoadModel>() {
@Override
public void onResponse(Call<RespUpLoadModel> call, Response<RespUpLoadModel> response) {
RespUpLoadModel responseCategory = response.body();
Log.i("data","onResponse() success !!");
}
@Override
public void onFailure(Call<RespUpLoadModel> call, Throwable t) {
}
});
}
public class RespUpLoadModel {
private int status;
private Img data;
private class Img {
private String img_url;
}
}
public interface IUpLoadIcon {
@POST("file/upload-img")
@Multipart
Call<RespUpLoadModel> upLoadIcon(@Part MultipartBody.Part phone);
}
Retrofit網(wǎng)絡(luò)請(qǐng)求:本質(zhì)上是OKHttp完成,而Retrofit僅負(fù)責(zé)網(wǎng)路請(qǐng)求的接口的封裝症见。實(shí)際上就是使用Retrofit的接口封裝我們請(qǐng)求的參數(shù)Hearder頭部喂走,URL信息等等,最后交給OKHttp來(lái)完成后續(xù)的網(wǎng)路請(qǐng)求操作筒饰。在服務(wù)端返回?cái)?shù)據(jù)給我們缴啡,OkHttp將原始的接口交給Retrofit。Retrofit根據(jù)用戶的需求對(duì)結(jié)果進(jìn)行不同類型的解析瓷们。
Retrofit進(jìn)行網(wǎng)絡(luò)請(qǐng)求的主要步驟:
1.創(chuàng)建描述網(wǎng)絡(luò)請(qǐng)求的接口
定義方法和相應(yīng)的注解:其內(nèi)部通過(guò)動(dòng)態(tài)代理的模式业栅,將我們接口和它的注解轉(zhuǎn)換成一個(gè)HTTP請(qǐng)求,最后再去執(zhí)行我們的HTTP請(qǐng)求谬晕。
接口里面的方法和參數(shù)碘裕,都必須要用注解的方式標(biāo)注,否者不標(biāo)注就會(huì)出錯(cuò)攒钳。
2.創(chuàng)建Retrofit實(shí)例
3.創(chuàng)建網(wǎng)絡(luò)請(qǐng)求接口實(shí)例并配置網(wǎng)絡(luò)請(qǐng)求參數(shù)
4.發(fā)送網(wǎng)絡(luò)請(qǐng)求(異步或者同步)
5.處理服務(wù)器返回的數(shù)據(jù)