方式一:使用okhttp3
okhttp官网
okhttp3 github地址
打开build.gradle.kts
文件加入依赖
dependencies {
implementation("com.squareup.okhttp3:okhttp:4.9.0")
}
在IDEA的Gradle
面板点击reload
按钮便会自动下载jar
使用网络请求时需要把网络的权限打开,不然会提示java.lang.SecurityException: Permission denied (missing INTERNET permission?)
诸如此类的报错
在AndroidManifest.xml
文件的manifest
节点下添加如下代码以表示使用网络权限
<uses-permission android:name="android.permission.INTERNET"/>
MainActivity.kt
代码如下
package com.demo.composestudy
import android.content.ContentValues.TAG
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
showUI()
}
}
}
@Composable
fun showUI(){
var resultstring by remember { mutableStateOf("") }
Column(){
Button(
onClick = {
var url = "https://www.baidu.com";
val client = OkHttpClient();
// 创建一个Request对象
var request: Request = Request.Builder()
.url(url)
.build();
//发起call请求
val call: Call = client.newCall(request)
//异步请求
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.d(TAG, "onFailure IOException:{$e}");
}
override fun onResponse(call: Call, response: Response) {
//接收返回响应
val result = response.body?.string()?:"";
resultstring = result;
Log.d(TAG, "result:{$result}");
}
});
}){
Text("点击进行请求")
}
Text(
"$resultstring",
Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleMedium
)
}
}
这里需要使用异步请求,使用同步请求会阻塞Android的UI线程
================================================
方式二:使用Retrofit2
Retrofit官网
Retrofit2快速入门
建议直接使用Retrofit2
步骤如下:
1.引入retrofit2
相关依赖(其中包括Gson转换器,用于返回JSON数据转化为Java对象)
2.创建一个API接口,用于定义业务需要的各种网络请求
3.创建retrofit实例
4.发送请求并处理返回结果
打开build.gradle.kts
文件加入依赖
dependencies {
implementation("com.google.code.gson:gson:2.11.0")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
}
由于日常开发所使用的站点接口一般是本地构建(通常是http的形式),而Android 9.0以上限制了明文的网络请求,非加密的请求都会被系统禁止掉。如果当前应用的请求是htttp请求,而非https请求,这样就会被Android系统禁止该请求,会出现类似java.net.UnknownServiceException: CLEARTEXT communication to xxxx.com not permitted by network security policy
等错误提示
在AndroidManifest.xml
文件的application
节点增加如下一行
android:usesCleartextTraffic="true"
先搭建一个本地测试站点,这里以https://demo.com为例
其中https://demo.com/site/user是根据id
和name
获取用户信息的接口地址
请求响应如下
{"id":1001,"name":"buyue"}
MainActivity.kt
代码如下
package com.demo.composestudy
import android.content.ContentValues.TAG
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
showUI()
}
}
}
data class User(val id: Int, val name: String)
interface ApiService{
@GET("site/user")
fun getUser(@Query("id") id: Int, @Query("name") name: String): Call<User>
}
@Composable
fun showUI(){
var resultstring by remember { mutableStateOf("") }
Column(){
Button(
onClick = {
var url = "https://demo.com";
var retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build()
var apiService = retrofit.create(ApiService::class.java)
apiService.getUser(1,"buyue").enqueue(object : Callback<User>{
override fun onResponse(call: Call<User>, response: Response<User>) {
var user = response.body()
Log.d(TAG,user.toString())
resultstring = "ID:" + user?.id + "\nName:" + user?.name
}
override fun onFailure(call: Call<User>, t: Throwable) {
Log.d(TAG,"onFailure",t)
}
})
}){
Text("点击进行请求")
}
Text(
"$resultstring",
Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleMedium
)
}
}
优化一下,封装统一返回值
修改https://demo.com/site/user请求响应如下
{"code":0,"message":"","data":{"id":1001,"name":"buyue"}}
调整MainActivity.kt
代码如下
package com.demo.composestudy
import android.content.ContentValues.TAG
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
showUI()
}
}
}
data class ApiResponse<T>(val code: Int, val message: String? = null, val data: T? = null)
data class User(val id: Int, val name: String)
interface ApiService{
@GET("site/user")
fun getUser(@Query("id") id: Int, @Query("name") name: String): Call<ApiResponse<User>>
}
@Composable
fun showUI(){
var resultstring by remember { mutableStateOf("") }
Column(){
Button(
onClick = {
var url = "https://demo.com"
var retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build()
var apiService = retrofit.create(ApiService::class.java)
apiService.getUser(1,"buyue").enqueue(object : Callback<ApiResponse<User>>{
override fun onResponse(call: Call<ApiResponse<User>>, response: Response<ApiResponse<User>>) {
//if (response.code() === 200) {
if (response.isSuccessful) {
// 请求成功,处理数据
val user = response.body()?.data
resultstring = "ID:" + user?.id + "\nName:" + user?.name
} else {
// 请求失败,处理错误信息
val message: String = response.message()
resultstring = message
}
}
override fun onFailure(call: Call<ApiResponse<User>>, t: Throwable) {
Log.d(TAG,"onFailure",t)
}
})
}){
Text("点击进行请求")
}
Text(
"$resultstring",
Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleMedium
)
}
}