Retrofit各个注解的含义及作用(项目经验和单个注解解释)
具体用法参照 Retrofit官网
简介
- 是一个基于okhttp的网络请求框架
- 通过注解配置网络请求参数
- 图片链接和图片上传
- 支持同步和异步网络请求
- 支持多种数据的解析,提供对Rxjava的支持
- 可拓展性好,高度封装,简洁易用
步骤
- 添加Retrofit库的依赖
- 创建接收服务器返回数据的类
- 创建用于描述网络请求的接口
- 创建 Retrofit 实例
- 创建 网络请求接口实例 并 配置网络请求参数
- 发送网络请求(异步 / 同步)
- 处理数据
1. GET
//简单的get请求(没有参数)
@GET("trades")
Call<TradesBean> getItem();
//简单的get请求(URL中带有参数)
@GET("News/{userId}")
Call<TradesBean> getItem(@Path("userId") String userId);
//简单的get请求(URL中带有两个参数)
@GET("News/{userId}")
Call<TradesBean> getItem(@Path("userId") String userId,@Path("type") String type);
//参数在url问号之后
@GET("trades")
Call<TradesBean> getItem(@Query("userId") String userId);
-
http://192.168.43.173/api/trades?userId={用户id}&type={类型}
(两种方法)
@GET("trades")
Call<TradesBean> getItem(@QueryMap Map<String, String> map);
@GET("trades")
Call<TradesBean> getItem(
@Query("userId") String userId,
@QueryMap Map<String, String> map);
@GET("{a}/json?")
Call<Bean> beanCall(@Path("a") int a, @Query("cid") String cid);
其他拼接方式
@GET
Call<ImageBean> getImageList3(@Url String url);
@GET
Call<ImageBean> getImageList4(@Url String url,@Query("uid") String uid);
2. POST
//需要补全URL,post的数据只有一条reason
@FormUrlEncoded
@POST("trades/{userId}")
Call<TradesBean> postResult(@Path("userId") String userId,
@Field("reason") String reason;
- http://192.168.43.173/api/trades/{userId}?token={token}
//需要补全URL,问号后需要加token,post的数据只有一条reason
@FormUrlEncoded
@POST("trades/{userId}")
Call<TradesBean> postResult(
@Path("userId") String userId,
@Query("token") String token,
@Field("reason") String reason;
//post一个对象
@POST("trades/{userId}")
Call<TradesBean> postResult(
@Path("userId") String userId,
@Query("token") String token,
@Body TradesBean bean;
//用不同注解post一个实体
@POST("trades/{userId}")
Call<TradesBean> postResult(
@Part("entity") TradesBean bean;
其他拼接方式
@POST("login")
@FormUrlEncoded
Call<LoginBean> login1(@Field("username") String username,@Field("password") String pw);
@POST
@FormUrlEncoded
Call<LoginBean> login3(@Url String url,@Field("username") String username,@Field("password") String password);
3. PUT
//put一个实体
@PUT("trade/carInfo/{pid}")
Call<TradesBean> putInfo
@Path("pid") Int pid,
@Body CarInfoBean carInfoBean;)
4. DELETE
http://192.168.43.173/api/trades/{userId}
//补全url
@DELETE("trades/{userId}")
Call<TradesBean> deleteInfo(
@Path("userId") String userId;
http://192.168.43.173/api/trades/{userId}?token={token}
//补全url并且后面还token
@DELETE("trades/{userId}")
Call<TradesBean> deleteInfo(
@Path("userId") String userId,
@Query("token") String token;)
5. 以Json格式提交数据 (模拟登录功能)两种方法
1、ApiService
/**
* 登录
*/
@Headers("Content-Type:application/json")
@POST("user/login")
Observable<ResponseBody> login(@Body RequestBody requestBody);
2、创建一个Bean类
public class UserBean {
private String nickname;
private String password;
public UserBean(String nickname, String password) {
this.nickname = nickname;
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3、将Bean类通过Gson转为json体
Gson gson = new Gson();
HashMap<String, String> map = new HashMap<>();
map.put("nickname", "123456");
map.put("password, "abcdefg");
String jsonBody = gson.toJson(map);
/ / 此时的jsonBody打印出来的结果
// {"password":"abcdefg","nickname":"123456"}
4、Retrofit请求头是否携带 如果请求带请求头 用方法一,如果不带请求头 用方法二,请求头需要添加的数据根据需求自行添加
1、不带请求头
private void useRetrofit(String url) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
apiServices = retrofit.create(ApiService.class);
}
2、带请求头
private void useHeaderRetrofit(String url) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.addHeader("Content-Type", "application/json;charset=utf-8")
.build();
return chain.proceed(request);
}
});
OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client)
.build();
apiServices = retrofit.create(ApiService.class);
}
5、网络请求的代码
RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), requestBody);
Observable<ResponseBody> responseBodyObservable = apiServices.login(body);
responseBodyObservable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<ResponseBody>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "e:" + e);
}
@Override
public void onNext(ResponseBody responseBody) {
try {
String string = responseBody.string();
Log.d("TAG", string);
callBack.onSuccess((T) string);
} catch (IOException e) {
e.printStackTrace();
}
}
});
第二种(简单方法)
String base_url = "https://www.firstgainfo.com/firstga/app/news/";
1. ApiService
//requestBody 获取下拉刷新数据
@Headers({"Content-Type:application/json"})
@POST("downListNews")
Call<ResponseBody> getDownList(@Body RequestBody body);
2 MainActivity中
private void getDownListData(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(MyServer.base_url)
.addConverterFactory(GsonConverterFactory.create())
.build();
MyServer myServer = retrofit.create(MyServer.class);
JSONObject param = new JSONObject();
try {
param.put("userId","d56ea66e7ee741f498ca51242c8c6394");
param.put("newsId","ad30af17a2ad44fca00a2d3f7e16c004");
RequestBody body = RequestBody.create(MediaType.parse("application/json"),param.toString());
Call<ResponseBody> call = myServer.getDownList(body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.i("response",response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i("onFailure",t.getMessage());
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
6 以form-data格式提交数据 (模拟登录功能)
1、ApiService
1、当数据量大的情况下用方法1 推荐此方法 处理数据时方便一些
/**
* 登录
*/
@Multipart
@POST("users/login")
Observable<ResponseBody> phoneLogin(@PartMap Map<String, RequestBody> requestBodyMap);
2、当数据量小的情况下用方法2
/**
* 登录
*/
@Multipart
@POST("users/login")
Call<JsonObject> phoneLogin(@Part("nickname") RequestBody username, @Part("password") RequestBody password);
2、转为form-data
/**
* 转换为 form-data
*
* @param requestDataMap
* @return
*/
public static Map<String, RequestBody> generateRequestBody(Map<String, String> requestDataMap) {
Map<String, RequestBody> requestBodyMap = new HashMap<>();
for (String key : requestDataMap.keySet()) {
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"),
requestDataMap.get(key) == null ? "" : requestDataMap.get(key));
requestBodyMap.put(key, requestBody);
}
return requestBodyMap;
}
3、Retrofit请求头是否携带 如果请求带请求头 用方法一,如果不带请求头 用方法二
1、不带请求头
private void useRetrofit(String url) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
apiServices = retrofit.create(ApiService.class);
}
2、带请求头
private void useHeaderRetrofit(String url) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.addHeader("Content-Type", "application/json;charset=utf-8")
.build();
return chain.proceed(request);
}
});
OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client)
.build();
apiServices = retrofit.create(ApiService.class);
}
第二种 (简单)
1. ApiService
String base_url = "https://www.firstgainfo.com/firstga/app/news/";
//获取详情数据
@Headers({"Content-Type:application/x-www-form-urlencoded"})
@POST("info")
@FormUrlEncoded
Observable<InfoBean> getData(@Field("userId") String userId, @Field("newsId") String newsId);
2. MainActivity
private void getData(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(MyServer.base_url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
MyServer myServer = retrofit.create(MyServer.class);
Observable<InfoBean> observable = myServer.getData("d56ea66e7ee741f498ca51242c8c6394","ad30af17a2ad44fca00a2d3f7e16c004");
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<InfoBean>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(InfoBean body) {
showInfo(body.getData().getContent());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
拼接经验
Path是网址中的参数,例如:trades/{userId}
Query是问号后面的参数,例如:trades/{userId}?token={token}
QueryMap 相当于多个@Query
Field用于Post请求,提交单个数据,然后要加@FormUrlEncoded
Body相当于多个@Field,以对象的方式提交
@Streaming:用于下载大文件
@Header,@Headers、加请求头
Gson解析报错的原因
- 参数拼接错误
- 看报错信息,一般封装出问题
- 对象改为 requestBody给泛型
- 采用原生解析