1. The okhttp library
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:4.1.0'
}
First you need to create an instance of OkHttpClient
val client = OkHttpClient()
Next, if you want to initiate an HTTP request, you need to create a Request object:
val request = Request.Builder().build()
Many other methods are added before the final build() method to enrich the Request object. For example, the network address of the target can be set by the url() method
val request = Request.Builder()
.url("https://www.baidu.com")
.build()
Then call the newCall() method of OkHttpClient to create a Call object, and call its execute() method to send the request and get the data returned by the server
val response = client.newCall(request).execute()
The Response object is the data returned by the server. We can use the following writing method to get the specific content returned
val responseData = response.body?.string()
POST requests are a little more complicated than GET requests. We need to build a Request Body object to store the parameters to be submitted.
val requestBody = FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build()
Then call the post() method in Request.Builder and pass in the RequestBody object
val request = Request.Builder()
.url("https://www.baidu.com")
.post(requestBody)
.build()
The next operation is the same as the GET request, just call the execute() method to send the request and get the data returned by the server.
use:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn.setOnClickListener {
sendRequestWithOkHttp()
}
}
...
private fun sendRequestWithOkHttp() {
thread {
try {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://www.baidu.com")
.build()
val response = client.newCall(request).execute()
val responseData = response.body?.string()
if (responseData != null) {
showResponse(responseData)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
2. Implementation of network request callback
An application is likely to use network functions in many places, and the code for sending HTTP requests is basically the same. If we write the code for sending HTTP requests every time, this is obviously a very bad practice, which can be encapsulated
object HttpUtil {
...
fun sendOkHttpRequest(address: String, callback: okhttp3.Callback) {
val client = OkHttpClient()
val request = Request.Builder()
.url(address)
.build()
client.newCall(request).enqueue(callback)
}
}
// 回调onFinish()方法
listener.onFinish(response.toString())
} catch (e: Exception) {
e.printStackTrace()
// 回调onError()方法
listener.onError(e)
} finally {
connection?.disconnect()
}
}
}
}
Two methods are defined in the interface: the onFinish() method means that it is called when the server successfully responds to our request, and the onError() means that it is called when an error occurs in the network operation. These two methods have parameters, the parameters in the onFinish() method represent the data returned by the server, and the parameters in the onError() method record the detailed information of the error.
interface HttpCallbackListener {
fun onFinish(response: String)
fun onError(e: Exception)
}
First add an HttpCallbackListener parameter to the sendHttpRequest() method, and open a sub-thread inside the method, and then perform specific network operations in the sub-thread. Note that the return statement cannot return data in the child thread, so here we pass the server response data into the onFinish() method of the HttpCallbackListener. If an exception occurs, pass the exception reason into the onError() method. Now the sendHttpRequest() method receives two parameters, so we also need to pass in the instance of HttpCallbackListener when calling it
HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {
override fun onFinish(response: String) {
// 得到服务器返回的具体内容
}
override fun onError(e: Exception) {
// 在这里对异常情况进行处理
}
})
In this way, when the server responds successfully, we can process the response data in the onFinish() method. Similarly, if an exception occurs, the exception can be handled in the onError() method. In this way, we cleverly use the callback mechanism to successfully return the response data to the caller.
There is an okhttp3.Callback parameter in the sendOkHttpRequest() method. This is the callback interface that comes with the OkHttp library, similar to the HttpCallbackListener we just wrote. Then after client.newCall(), instead of calling the execute() method as before, it calls an enqueue() method and passes in the okhttp3.Callback parameter. I believe you have guessed the smart ones. OkHttp has opened the sub-thread for us inside the enqueue() method, and then executes the HTTP request in the sub-thread, and calls back the final request result to okhttp3.Callback. Then we can write like this when calling the sendOkHttpRequest() method
HttpUtil.sendOkHttpRequest(address, object : Callback {
override fun onResponse(call: Call, response: Response) {
// 得到服务器返回的具体内容
val responseData = response.body?.string()
}
override fun onFailure(call: Call, e: IOException) {
// 在这里对异常情况进行处理
}
})
It should be noted that whether using HttpURLConnection or OkHttp, the final callback interface is still running in the child thread, so we cannot perform any UI operations here, unless the thread conversion is performed with the help of the runOnUiThread() method
Next: How to use Retrofit