【Android】HttpURLConnection、OkHttp

WebView 已经在后台帮我们处理好了发送HTTP请求、接收服务器响应、解析返回数据,以及最终的页面展示这几步工作。只不过它封装得实在是太好了,反而使得我们不能那么直观地看出HTTP到底是如何工作的。因此,接下来我们通过手动发送HTTP请求的方式,更加深入地理解这个过程。

在过去,Android上发送HTTP请求一般有两种方式:HttpURLConnection 和HttpClient 。不过由于HttpClient 存在API数量过多、扩展困难等缺点,Android团队越来越不建议我们使用这种方式。终于在Android 6.0 系统中,HttpClient 的功能被完全移除了,标志着此功能被正式弃用。

现在,官方建议使用的HttpURLConnection

HttpURLConnection

kt 复制代码
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 
		}
	}
}
xml 复制代码
<!-- AndroidManifest.xml 声明一下网络权限-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
	package="com.example.networktest">
	<uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>
xml 复制代码
<!-- activity_main.xml -->
<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>

提交数据给服务器:

kt 复制代码
connection.requestMethod = "POST"
val output = DataOutputStream(connection.outputStream) output.writeBytes("username=admin&password=123456")

OkHttp

js 复制代码
dependencies {
    ...
	implementation 'com.squareup.okhttp3:okhttp:4.1.0' 
}

下面我们来看一下OkHttp 的具体用法。

首先,需要创建一个OkHttpClient的实例,如下所示:

kt 复制代码
val client = OkHttpClient()

接下来如果想要发起一条HTTP请求,就需要创建一个Request对象:

kt 复制代码
val request = Request.Builder().build()

当然,上述代码只是创建了一个空的Request对象,并没有什么实际作用,我们可以在最终的 build()方法之前连缀很多其他方法来丰富这个Request对象。比如,可以通过url()方法来设置目标的网络地址,如下所示:

kt 复制代码
val request = Request.Builder()
		.url("https://www.baidu.com")
		.build()

之后调用OkHttpClient 的newCall()方法来创建一个Call对象,并调用它的execute()方法 来发送请求并获取服务器返回的数据,写法如下:

kt 复制代码
val response = client.newCall(request).execute()

Response对象就是服务器返回的数据了,我们可以使用如下写法来得到返回的具体内容:

kt 复制代码
val responseData = response.body?.string()

如果是发起一条POST请求,会比GET请求稍微复杂一点,我们需要先构建一个Request Body 对象来存放待提交的参数,如下所示:

kt 复制代码
val requestBody = FormBody.Builder() 
		.add("username", "admin")
		.add("password", "123456") 
		.build()

然后在Request.Builder 中调用一下post()方法,并将RequestBody对象传入:

kt 复制代码
val request = Request.Builder() 
		.url("https://www.baidu.com")
		.post(requestBody) 
		.build()

接下来的操作就和GET请求一样了,调用execute()方法来发送请求并获取服务器返回的数据即可。

相关推荐
帅得不敢出门9 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了10 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任12 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山12 小时前
Android“引用们”的底层原理
android·java
迃-幵13 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶13 小时前
Android——从相机/相册获取图片
android
Rverdoser13 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj13 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang14 小时前
android10 蓝牙(二)配对源码解析
android
Liknana14 小时前
Android 网易游戏面经
android·面试