使用 OkHttp
- 首先需要在项目中添加 OkHttp库 的依赖
dependencies {
......
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
}
- 创建一个OkHttpClient实例
val client = OkHttpClient()
- 创建一个Request对象
val request = Request.Builder().url("https://www.baidu.com").build()
- 调用 OkHttpClient 的 newCall() 方法来创建一个Call对象,并调用它的 execute() 方法来发送请求,并获取从服务器返回的数据。
val response = client.newCall(request).execute()
- 该response对象即为服务器返回的数据,可进行查看
response.body?.string()
发起POST请求
- 构建一个 Request Body 对象来存放待提交数据
val requestBody = FormBody.Builder().add("username", "admin").add("password", "123456").build()
- 在Request.Builder中调用 post() 方法,并将 Request Body 对象传入
val request = Request.Builder().url("https://www.baidu.com").post(requestBody).build()
全部代码如下:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn = findViewById(R.id.sendRequestBtn)
responseText = findViewById(R.id.responseText)
sendRequestBtn.setOnClickListener {
sendRequestWithOkHttp()
}
}
private fun sendRequestWithOkHttp() {
thread {
try {
val client = OkHttpClient()
val requestBody =
FormBody.Builder().add("username", "admin").add("password", "123456").build()
val request = Request.Builder().url("https://www.baidu.com").post(requestBody).build()
val response = client.newCall(request).execute()
val responseData = response.body?.string()
if (responseData != null) showResponse(responseData)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
解析 JSON数据
(一) 使用JSONObject
- 首先,调用OkHttp从网页获取数据
private fun sendRequestWithOkHttp() {
thread {
try {
//创建一个OkHttpClient实例
val client = OkHttpClient()
//创建要请求的对象
val request = Request.Builder().url("").build()
//调用实例的 Call 方法来发出请求,同时请求数据
val response = client.newCall(request).execute()
//获取请求的数据
val responseData = response.body?.string()
//当请求的数据不为空时,进行对应格式数据解析
if (responseData != null) {
parseJSONWithJSONObject(responseData)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
- 通过JSONObject 来进行JSON格式数据解析,方法实现如下:
private fun parseJSONWithJSONObject(jsonData: String) {
try {
//根据获取的数据类型,来创建对应的数据结构进行数据保存
val jsonArray = JSONArray(jsonData)
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
val id = jsonObject.getString("id")
val version = jsonObject.getString("version")
val name = jsonObject.getString("name")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
根据获取的数据类型,来创建对应的数据结构进行数据保存。然后遍历数据结构,获取想要的数据。本例子使用的JSON数据如下所示:
[{"id":"5","version":"5.5","name":"Clash of Clans"},
{"id":"6","version":"7.0","name":"Boom Beach"},
{"id":"7","version":"3.5","name":"Clash Royale"}]
(二) 使用GSON
Google提供的GSON开源库可以让解析JSON数据的工作简单到让你不敢想象的地步!
如果想要使用GSON需要首先添加GSON依赖库,GSON的强大之处在于将一段JSON格式的字符串自动映射成一个对象,从而不需要手动编写代码进行解析!!!!!
- 添加GSON依赖库
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:4.4.1'
implementation 'com.google.code.gson:gson:2.8.6'
}
- 如果一段JSON格式数据为
{"name":"Tom","age":20}
可以定义一个Person类,并加入 name 和 age 两个字段,然后调用 GSON 的 fromJson() 就可以自动解析成一个Person对象了。
//需要先创建一个Gson实例
val gson = Gson()
val person = gson.fromJson(responseData, Person::class.java)
需要先创建一个Gson实例,然后调用 fromJson() .
- 如果一段JSON格式数据为
[{"name":"Tom","age":20}, {"name":"Jack","age":25}, {"name":"Lily","age":22}]
需要借助 TypeToken 将期望解析成的数据类型传入 fromJson() 方法中,如下所示:
val typeOf = object : TypeToken<List<Person>>() {}.type
val people = gson.fromJson<List<Person>>(responseData,typeOf)
示例代码如下,新建一个App类,将JSON格式存储为App对象:
private fun parseJSONWithGson(jsonData: String) {
try {
val gson = Gson()
val typeOf = object : TypeToken<List<App>>() {}.type
val appList = gson.fromJson<List<App>>(jsonData, typeOf)
for (app in appList) {
//业务逻辑
}
} catch (e: Exception) {
e.printStackTrace()
}
}
网络请求回调的实现方式
一个项目中可能用到很多网络请求,如果每一次都需要编写相同代码,非常差劲。
通常情况下,将这些通用的网络操作提取到一个公共的类中,当需要网络请求时,调用方法即可。
需要网络请求回调的原因:
网络请求通常属于耗时操作,而sendHttpRequest()方法的内部并没有开启线程。如果我们在sendHttpRequest()方法中开启一个线程来发起HTTP请求,服务器响应的数据是无法进行返回的。这是由于所有的耗时逻辑都是在子线程里进行的,sendHttpRequest()方法会在服务器还没来得及响应的时候就执行结束了,当然也就无法返回响应的数据了。
使用HTTP来进行网络请求
需要重新定义一个接口,进行回调。
interface HttpCallbackListener {
fun onFinish(response: String)
fun onError(e:Exception)
}
object HttpUtil {
......
fun sendHttpRequest(address: String, listener: HttpCallbackListener) {
thread {
var connection: HttpURLConnection? = null
try {
val response = StringBuilder()
val url = URL(address)
connection = url.openConnection() as HttpURLConnection
connection.connectTimeout = 8000
connection.readTimeout = 8000
val input = connection.inputStream
val reader = BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
response.append(it)
}
}
// 回调onFinish()方法
listener.onFinish(response.toString())
} catch (e: Exception) {
e.printStackTrace()
// 回调onError()方法
listener.onError(e)
} finally {
connection?.disconnect()
}
}
}
}
调用时还需要将 HttpCallbackListener 的实例传入,然后重写接口中的两个方法。
private fun sendRequestWithHttpURLConnection() {
val address = "https://www.baidu.com"
HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {
override fun onFinish(response: String) {
//从服务器返回的内容
showResponse(response)
}
override fun onError(e: Exception) {
//对异常情况进行处理
}
})
}
private fun showResponse(response: String) {
responseText.text = response
}
调用时:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn = findViewById(R.id.sendRequestBtn)
responseText = findViewById(R.id.responseText)
sendRequestBtn.setOnClickListener {
sendRequestWithHttpURLConnection()
// sendRequestWithOkHttp()
}
}
使用OkHttp来进行网络请求
在公共类中定义如下:
object HttpUtil {
fun sendOkHttpRequest(address: String, callback: okhttp3.Callback) {
var connection: HttpURLConnection? = null
try {
val client = OkHttpClient()
val request = Request.Builder().url(address).build()
client.newCall(request).enqueue(callback)
} catch (e: Exception) {
e.printStackTrace()
}
}
......
}
sendOkHttpRequest()方法中有一个okhttp3.Callback参数,这个是OkHttp库中自带的回调接口,类似于我们刚才自己编写的HttpCallbackListener。然后在client.newCall()之后没有像之前那样一直调用execute()方法,而是调用了一个enqueue()方法,并把okhttp3.Callback参数传入。
OkHttp在 enqueue() 方法的内部已经帮我们开好子线程了,
private fun sendRequestWithOkHttp() {
val address = "https://www.baidu.com"
HttpUtil.sendOkHttpRequest(address, object : Callback {
override fun onFailure(call: Call, e: IOException) {
//对异常情况进行处理
}
override fun onResponse(call: Call, response: Response) {
//得到从服务器返回的具体内容
val responseData = response.body?.string()
}
})
}
调用时:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn = findViewById(R.id.sendRequestBtn)
responseText = findViewById(R.id.responseText)
sendRequestBtn.setOnClickListener {
// sendRequestWithHttpURLConnection()
sendRequestWithOkHttp()
}
}