前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android使用Retrofit进行网络请求及和Kotlin结合使用

Android使用Retrofit进行网络请求及和Kotlin结合使用

作者头像
码客说
发布2024-03-29 12:47:26
3280
发布2024-03-29 12:47:26
举报
文章被收录于专栏:码客码客

前言

Retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。

准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。

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

基本配置

添加网络权限

代码语言:javascript
复制
<uses-permission android:name="android.permission.INTERNET"/>

添加依赖

代码语言:javascript
复制
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")

注解

Retrofit使用大量注解来简化请求,Retrofit将okhttp请求抽象成接口,使用注解来配置和描述网络请求参数。

请求方法注解

请求方法注解

说明

@GET

get请求

@POST

post请求

@PUT

put请求

@DELETE

delete请求

@PATCH

patch请求,该请求是对put请求的补充,用于更新局部资源

@HEAD

head请求

@OPTIONS

options请求

@HTTP

通过注解,可以替换以上所有的注解,它拥有三个属性:method、path、hasBody

请求头注解

请求头注解

说明

@Headers

用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在

@Header

作为方法的参数传入,用于添加不固定的header,它会更新已有请求头

请求参数注解

请求参数注解

说明

@Body

多用于Post请求发送非表达数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据,添加GsonConverterFactory则是将body转化为json字符串进行传递

@Filed

多用于Post方式传递参数,需要结合@FromUrlEncoded使用,即以表单的形式传递参数

@FiledMap

多用于Post请求中的表单字段,需要结合@FromUrlEncoded使用

@Part

用于表单字段,Part和PartMap与@multipart注解结合使用,适合文件上传的情况

@PartMap

用于表单字段,默认接受类型是Map<String,RequestBody>,可用于实现多文件上传

@Path

用于Url中的占位符

@Query

用于Get请求中的参数

@QueryMap

与Query类似,用于不确定表单参数

@Url

指定请求路径

请求和响应格式(标记)注解

标记类注解

说明

@FormUrlEncoded

表示请求发送编码表单数据,每个键值对需要使用@Filed注解

@Multipart

表示请求发送form_encoded数据(使用于有文件上传的场景),每个键值对需要用@Part来注解键名,随后的对象需要提供值

@Streaming

表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用

参数示例

URL上的参数

代码语言:javascript
复制
@GET("user")
Call<ResponseBody> getData2(@Query("id") long idLon, @Query("name") String nameStr);

@GET("user")
Call<ResponseBody> getData3(@QueryMap Map<String, Object> map);

Post请求-Form形式

代码语言:javascript
复制
@FormUrlEncoded
@POST("user/emails")
Call<ResponseBody> getPostData2(@Field("name") String nameStr, @Field("sex") String sexStr);

 @FormUrlEncoded
 @POST("user/emails")
 Call<ResponseBody> getPsotData3(@FieldMap Map<String, Object> map);

Post请求-JSON形式

代码语言:javascript
复制
@POST("user/emails")
Call<ResponseBody> getPsotDataBody(@Body RequestBody body);

URL上占位符

代码语言:javascript
复制
@GET("orgs/{id}")
Call<ResponseBody> getPathData(@Query("name") String nameStr, @Path("id") long idLon);

文件上传

代码语言:javascript
复制
@Multipart
@POST("user/followers")
Call<ResponseBody> getPartData(@Part("name") RequestBody name, @Part MultipartBody.Part file);

调用

代码语言:javascript
复制
//声明类型,这里是文字类型
 MediaType textType = MediaType.parse("text/plain");
//根据声明的类型创建RequestBody,就是转化为RequestBody对象
RequestBody name = RequestBody.create(textType, "这里是你需要写入的文本:刘亦菲");
 
//创建文件,这里演示图片上传
File file = new File("文件路径");
if (!file.exists()) {
   file.mkdir();
 }
 
//将文件转化为RequestBody对象
//需要在表单中进行文件上传时,就需要使用该格式:multipart/form-data
RequestBody imgBody = RequestBody.create(MediaType.parse("image/png"), file);
//将文件转化为MultipartBody.Part
//第一个参数:上传文件的key;第二个参数:文件名;第三个参数:RequestBody对象
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), imgBody);
 
Call<ResponseBody> partDataCall = retrofit.create(Api.class).getPartData(name, filePart);

多文件上传

代码语言:javascript
复制
@Multipart
@POST("user/followers")
Call<ResponseBody> getPartMapData(@PartMap Map<String, MultipartBody.Part> map);

调用

代码语言:javascript
复制
File file1 = new File("文件路径");
File file2 = new File("文件路径");
    if (!file1.exists()) {
    file1.mkdir();
}
    if (!file2.exists()) {
    file2.mkdir();
}

RequestBody requestBody1 = RequestBody.create(MediaType.parse("image/png"), file1);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("image/png"), file2);
MultipartBody.Part filePart1 = MultipartBody.Part.createFormData("file1", file1.getName(), requestBody1);
MultipartBody.Part filePart2 = MultipartBody.Part.createFormData("file2", file2.getName(), requestBody2);

Map<String,MultipartBody.Part> mapPart = new HashMap<>();
    mapPart.put("file1",filePart1);
    mapPart.put("file2",filePart2);

Call<ResponseBody> partMapDataCall = retrofit.create(Api.class).getPartMapData(mapPart);

整体示例

假如我们要请求

https://www.psvmc.cn/userlist.json

添加实体

代码语言:javascript
复制
import java.util.List;

public class ResultListVo<T> {
    private int code;
    private String msg;
    private List<T> obj;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public List<T> getObj() {
        return obj;
    }

    public void setObj(List<T> obj) {
        this.obj = obj;
    }
}

用户

代码语言:javascript
复制
public class UserVo {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

请求接口类

代码语言:javascript
复制
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface UserApi {
    //get请求
    @GET("userlist.json")
    Call<ResultListVo<UserVo>> getUserList();
}

创建Retrofit实例

代码语言:javascript
复制
//构建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
        //设置网络请求BaseUrl地址
        .baseUrl("https://www.psvmc.cn/")
        //设置数据解析器
        .addConverterFactory(GsonConverterFactory.create())
        .build();

接口对象实例

代码语言:javascript
复制
//创建网络请求接口对象实例
UserApi userApi = mRetrofit.create(UserApi.class);
//对发送请求进行封装
Call<ResultListVo<UserVo>> resultCall = userApi.getUserList();

调用

同步调用

代码语言:javascript
复制
//同步请求
Response<ResultListVo<UserVo>> data= resultCall.execute();

异步调用

代码语言:javascript
复制
//异步请求
resultCall.enqueue(new Callback<ResultListVo<UserVo>>() {
    //请求成功回调
    @Override
    public void onResponse(Call<ResultListVo<UserVo>> call, Response<ResultListVo<UserVo>> response) {
		ResultListVo<UserVo> body = response.body();
    }
    //请求失败回调
    @Override
    public void onFailure(Call<ResultListVo<UserVo>> call, Throwable t) {         
    }
});

Kotlin

新版本的Retrofit已经可以方便使用Kotlin的协程。

服务接口

添加suspend关键字,返回类型Response<T>

代码语言:javascript
复制
import com.xhkjedu.xh_control_appstore.model.ResultListVo
import com.xhkjedu.xh_control_appstore.model.UserVo
import retrofit2.Response
import retrofit2.http.GET

interface UserApi {
    //get请求
    @GET("userlist.json")
    suspend fun getUserList(): Response<ResultListVo<UserVo>>
}

调用

简单调用

代码语言:javascript
复制
GlobalScope.launch {
    var result = ApiManager.userApi.getUserList().body()
    Log.i("API", Gson().toJson(result))
}

ViewModel中调用

BaseViewModel

代码语言:javascript
复制
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

open class BaseViewModel : ViewModel() {
    var zIsShowMsg = mutableStateOf(false)
    var zShowMsgContent = mutableStateOf("")

    fun mLaunch(block: suspend () -> Unit) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                block()
            } catch (e: Exception) {
                withContext(Dispatchers.Main){
                    zIsShowMsg.value = true
                    zShowMsgContent.value = "接口请求失败"
                }
            }
        }
    }
}

UserViewModel

代码语言:javascript
复制
import android.util.Log
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.google.gson.Gson
import com.xhkjedu.xh_control_appstore.api.ApiManager
import com.xhkjedu.xh_control_appstore.model.UserVo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class UserViewModel : BaseViewModel() {
    val userList = mutableStateListOf<UserVo>()
    fun loadData() {
        mLaunch {
            Log.i("API2", Thread.currentThread().name)
            val result = ApiManager.userApi.getUserList().body()
            withContext(Dispatchers.Main) {
                result?.let {
                    if (result.code == 0) {
                        userList.addAll(result.obj)
                        zIsShowMsg.value = false
                    } else {
                        zIsShowMsg.value = true
                        zShowMsgContent.value = result.msg
                    }
                }
            }
        }
    }
}

代理HTTPS无法请求

查看

https://www.psvmc.cn/article/2019-04-03-win-proxy.html

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 基本配置
  • 注解
    • 请求方法注解
      • 请求头注解
        • 请求参数注解
          • 请求和响应格式(标记)注解
          • 参数示例
            • URL上的参数
              • Post请求-Form形式
                • Post请求-JSON形式
                  • URL上占位符
                    • 文件上传
                      • 多文件上传
                      • 整体示例
                        • 添加实体
                          • 请求接口类
                            • 创建Retrofit实例
                              • 接口对象实例
                                • 调用
                                • Kotlin
                                  • 服务接口
                                    • 调用
                                      • 简单调用
                                      • ViewModel中调用
                                  • 代理HTTPS无法请求
                                  领券
                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                                  http://www.vxiaotou.com