WebView 已经在后台帮我们处理好了发送HTTP请求、接收服务器响应、解析返回数据,以及最终的页面展示这几步工作。只不过它封装得实在是太好了,反而使得我们不能那么直观地看出HTTP到底是如何工作的。因此,接下来我们通过手动发送HTTP请求的方式,更加深入地理解这个过程。
在过去,Android上发送HTTP请求一般有两种方式:HttpURLConnection 和HttpClient 。不过由于HttpClient 存在API数量过多、扩展困难等缺点,Android团队越来越不建议我们使用这种方式。终于在Android 6.0 系统中,HttpClient 的功能被完全移除了,标志着此功能被正式弃用。
现在,官方建议使用的HttpURLConnection
。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn.setOnClickListener {
sendRequestWithHttpURLConnection()
}
}
/**
在这个方法中先是开启了一个子线程,然后在子线程里使用HttpURLConnection 发出一条HTTP请求。
*/
private fun sendRequestWithHttpURLConnection() { // 开启线程发起网络请求
thread {
var connection: HttpURLConnection? = null
try {
val response = StringBuilder()
//首先,需要获取HttpURLConnection 的实例,一般只需创建一个URL对象,并传入目标的网络地 址
val url = URL("https://www.baidu.com")
//然后,调用一下openConnection()方法即可
connection = url.openConnection() as HttpURLConnection
//设置:HTTP请求所使用的方法、连接超时、读取超时的毫秒数
connection.requestMethod = "GET"
connection.connectTimeout = 8000
connection.readTimeout = 8000
//之后,再调用getInputStream()方法就可以获取到服务器返回的输入流了
val input = connection.inputStream
//接着利用BufferedReader 对服务器返回的流进行读取
val reader = BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
response.append(it)
}
}
//将结果传入showResponse() 方法中。
showResponse(response.toString())
} catch (e: Exception) {
e.printStackTrace()
} finally {
connection?.disconnect()
}
}
}
private fun showResponse(response: String) {
runOnUiThread {
// 在这里进行UI操作,将结果显示到界面上
responseText.text = response
}
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.networktest">
<uses-permission android:name="android.permission.INTERNET" />
...
manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/sendRequestBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/responseText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
ScrollView>
LinearLayout>
提交数据给服务器:
connection.requestMethod = "POST"
val output = DataOutputStream(connection.outputStream) output.writeBytes("username=admin&password=123456")
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:4.1.0'
}
下面我们来看一下OkHttp 的具体用法。
首先,需要创建一个OkHttpClient的实例,如下所示:
val client = OkHttpClient()
接下来如果想要发起一条HTTP请求,就需要创建一个Request对象:
val request = Request.Builder().build()
当然,上述代码只是创建了一个空的Request对象,并没有什么实际作用,我们可以在最终的 build()方法之前连缀很多其他方法来丰富这个Request对象。比如,可以通过url()方法来设置目标的网络地址,如下所示:
val request = Request.Builder()
.url("https://www.baidu.com")
.build()
之后调用OkHttpClient 的newCall()方法来创建一个Call对象,并调用它的execute()方法 来发送请求并获取服务器返回的数据,写法如下:
val response = client.newCall(request).execute()
Response对象就是服务器返回的数据了,我们可以使用如下写法来得到返回的具体内容:
val responseData = response.body?.string()
如果是发起一条POST请求,会比GET请求稍微复杂一点,我们需要先构建一个Request Body 对象来存放待提交的参数,如下所示:
val requestBody = FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build()
然后在Request.Builder 中调用一下post()方法,并将RequestBody对象传入:
val request = Request.Builder()
.url("https://www.baidu.com")
.post(requestBody)
.build()
接下来的操作就和GET请求一样了,调用execute()方法来发送请求并获取服务器返回的数据即可。