Retrofit 使用
Retrofit 官网
https://square.github.io/retrofit/
导入依赖库
// retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
// 或
// implementation 'com.squareup.retrofit2:retrofit:(insert latest version)'
// gson 解析数据,直接转换成需要的实体类或其他类型(可以不添加)
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
// 数据请求
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
请求数据(以 玩Android 为例,官方文档为 github 接口:https://api.github.com/)
-
数据请求前提
- 数据
val baseurl = "https://www.wanandroid.com" val username = "bin" val password = "123456"
- 创建请求的接口文件 Api.class
interface Api{ // 登陆 @FormUrlEncoded @POST("/user/login") fun login(@Field("username") username:String, @Field("password") password:String) : Call<WanAndroidResponse<WanAndroidUser>> // 首页文章列表 @GET("/article/list/{page}/json") fun homeArticleList(@Path("page") page:Int) : Call<WanAndroidResponse<ArticleList>> }
- 创建 Retrofit 对象
val retrofit: Retrofit = Retrofit.Builder() .baseUrl(baseurl) .addConverterFactory(GsonConverterFactory.create()) .build()
- 创建 Api 对象
var mApi: Api = retrofit.create(Api::class.java)
- 数据
-
get
mApi.homeArticleList(0).also { it.enqueue(object : Callback<WanAndroidResponse<ArticleList>> { override fun onFailure( call: Call<WanAndroidResponse<ArticleList>>?, t: Throwable? ) { Log.e(TAG, "getHomeArticleList onFailure:\n ${t.toString()}\n${call.toString()}" ) } override fun onResponse( call: Call<WanAndroidResponse<ArticleList>>?, response: Response<WanAndroidResponse<ArticleList>>? ) { Log.e(TAG, "getHomeArticleList onResponse: ${response!!.body().toString()}" ) } }) }
-
post
mApi.login(username, password).also { it.enqueue(object : Callback<WanAndroidResponse<WanAndroidUser>> { override fun onFailure(call: Call<WanAndroidResponse<WanAndroidUser>>, t: Throwable) { Log.e(TAG, "login onFailure:\n ${t.toString()}\n${call.toString()}" ) } override fun onResponse( call: Call<WanAndroidResponse<WanAndroidUser>>, response: Response<WanAndroidResponse<WanAndroidUser>> ) { Log.e(TAG, "login onResponse: ${response.body().toString()}" ) Log.e(TAG, "onResponse: ${response.headers()}" ) cookieList = response.headers().values("Set-Cookie") Log.e(TAG, "onResponse: ${response.headers().values("Set-Cookie")}\n${cookieList.size}" ) } }) }
-
提交图片
@Multipart @POST("home/upload-image") Call<PictureBean> setHttpPortrait(@Part MultipartBody.Part part);
private void setHttpPortrait(final String name, final String strPath) {//name:参数名称;strPath:图片路径 File file = new File(strPath); RequestBody imageBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); MultipartBody.Part imageBodyPart = MultipartBody.Part.createFormData(name, file.getName(), imageBody); Call<PictureBean> repos = xxx.setHttpPortrait(imageBodyPart); repos.enqueue(new Callback<PictureBean>() { @Override public void onResponse(Call<PictureBean> call, Response<PictureBean> response) { try { if (response.body().isOk()) {//请求成功 //返回数据处理 } else { //图片上传失败 } } catch (Exception e) { //返回数据异常 } } @Override public void onFailure(Call<PictureBean> call, Throwable t) { //请求异常 } }); }
@Multipart @POST("home/upload-image")//多张上传图片 Call<PictureBean> setHttpDataPortrait(@Part List file);
private void setHttpPortrait(final String name, final List<String> paths) { showLoading(); MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); for (String path : paths) { File file = new File(path); RequestBody requestBody = RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"), file); builder.addFormDataPart("files", file.getName(), requestBody); } List parts = builder.build().parts(); Call<PictureBean> repos = xxx.setHttpDataPortrait(parts); repos.enqueue(new Callback<PictureBean>() { @Override public void onResponse(Call<PictureBean> call, Response<PictureBean> response) { try { if (response.body().isOk()) { //返回数据处理 } else { //图片上传失败 } } catch (Exception e) { //返回数据异常 } } @Override public void onFailure(Call<PictureBean> call, Throwable t) { //请求异常 } }); }
-
执行请求,并处理返回结果
mApi.xxx().enqueue(object : Callback<ResponseBody> { override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) { // 请求成功,进行后续处理 } override fun onFailure(call: Call<ResponseBody>, t: Throwable) { // 请求失败,进行后续处理 } })
注解的含义及使用
- 请求方法
- @GET
- @POST
- @PUT
- @DELETE
- @PATH
- @HEAD
- @OPTIONS
- @HTTP
- 标记类
- @FormUrlEncoded
表示请求主体是表单 - @Multipart
表示请求主体是支持文件上传的表单 - @Streaming
表示返回的数据以流的形式返回。适用于返回数据较大的场景(没使用过)
- @FormUrlEncoded
- 请求参数
-
@Headers
添加请求头(固定的请求头)@Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App" }) @GET("users/{username}") Call<User> getUser(@Path("username") String username);
@Headers("Cache-Control: max-age=640000") @GET("widget/list") Call<List<Widget>> widgetList();
-
@HeaderMap
添加请求头(不固定的请求头)@GET("user") Call<User> getUser(@HeaderMap Map<String, String> headers)
-
@Header
添加单个请求头(不固定的请求头)@GET("user") Call<User> getUser(@Header("Authorization") String authorization)
-
@Body
用于非表单请求体(传实体类对象或其他自己需要的类型)@POST("users/new") Call<User> createUser(@Body User user);
@POST("auth/guest") Call<BaseResponse<TokenInfo>> guest(@Body RequestBody requestBody);
-
@Field
向 post 表单传入键值对@FormUrlEncoded @POST("user/edit") Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
-
@FieldMap
向 post 表单传入多个键值对@FormUrlEncoded @POST("user/edit") Call<User> updateUser(@FieldMap Map<String, String> fields);
-
@Part
向 post 表单传入键值对(需要上传文件的场景)@Multipart @POST("/") Call<ResponseBody> example( @Part("description") String description, @Part(value = "image", encoding = "8-bit") RequestBody image);
@Multipart @POST("home/upload-image") Call<PictureBean> setHttpPortrait(@Part MultipartBody.Part part);
-
@PartMap
向 post 表单传入多个键值对(需要上传文件的场景)@Multipart @POST("/upload") Call<ResponseBody> upload( @Part("file") RequestBody file, @PartMap Map<String, RequestBody> params);
@Multipart @POST("home/upload-image")//多张上传图片 Call<PictureBean> setHttpDataPortrait(@Part List file);
-
@Query
向 get 请求传入参数及对应的值@GET("/friends") Call<ResponseBody> friends(@Query("page") int page);
-
@QueryMap
向 get 请求传入多个参数及对应的值@GET("/friends") Call<ResponseBody> friends(@QueryMap Map<String, String> filters);
-
@Path
向 get 请求传入链接的缺省值@GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user);
-