- 传统方式:使用
HttpURLConnection(适用于较旧的 API 或不想引入第三方库的场景) - 现代方式:使用第三方库
Retrofit+OkHttp+Gson(目前业界最主流、最推荐的方式)
概念:Android 网络请求的基本流程
- 发起请求: 客户端(你的 App)向服务器指定的 URL 发送一个网络请求。
- 服务器响应: 服务器处理请求,并返回一个响应,其中包含状态码(如 200 表示成功)和响应体(即 XML 数据)。
- 解析响应: 客户端接收到 XML 数据后,需要将其解析成 Android 可以方便操作的 Java/Kotlin 对象。
- 更新 UI: 将解析后的数据展示在界面上。
使用 HttpURLConnection (原生 API)
这是 Android SDK 自带的网络请求方式,无需添加任何依赖。

步骤 1: 添加网络权限
在 app/src/main/AndroidManifest.xml 文件中,必须声明网络权限。
<manifest ...>
<!-- 允许应用访问网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
...
</application>
</manifest>
步骤 2: 在后台线程执行网络请求
非常重要! Android 4.0 (API level 11) 以后,网络操作不允许在主线程(UI 线程)中进行,否则会抛出 NetworkOnMainThreadException 异常,我们可以使用 AsyncTask、Thread + Handler 或现代的 Coroutines/RxJava 来在后台执行任务。
这里我们使用 AsyncTask 作为示例(虽然它已不推荐用于新项目,但非常适合演示基本原理)。
步骤 3: 编写代码获取和解析 XML
假设服务器返回一个简单的 XML 文件,内容如下:

<users>
<user>
<id>1</id>
<name>张三</name>
<email>zhangsan@example.com</email>
</user>
<user>
<id>2</id>
<name>李四</name>
<email>lisi@example.com</email>
</user>
</users>
完整代码示例:
import android.os.AsyncTask
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL
import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.DocumentBuilderFactory
class MainActivity : AppCompatActivity() {
private lateinit var tvResult: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvResult = findViewById(R.id.tvResult)
val btnFetch: Button = findViewById(R.id.btnFetch)
btnFetch.setOnClickListener {
// 执行异步任务
FetchXmlTask().execute("https://your-server.com/path/to/users.xml")
}
}
// AsyncTask 的三个泛型参数分别是:
// Params: execute() 方法传入的参数类型 (String)
// Progress: 后台任务执行进度的类型 (这里不需要)
// Result: 后台任务返回的结果类型 (String)
private inner class FetchXmlTask : AsyncTask<String, Void, String>() {
override fun doInBackground(vararg params: String): String? {
val urlString = params[0]
var connection: HttpURLConnection? = null
var inputStream: InputStream? = null
return try {
val url = URL(urlString)
connection = url.openConnection() as HttpURLConnection
connection.connect()
val responseCode = connection.responseCode
if (responseCode == HttpURLConnection.HTTP_OK) {
inputStream = connection.inputStream
parseXml(inputStream)
} else {
"Error: HTTP Response Code $responseCode"
}
} catch (e: Exception) {
e.printStackTrace()
"Error: ${e.message}"
} finally {
inputStream?.close()
connection?.disconnect()
}
}
override fun onPostExecute(result: String?) {
// 在主线程更新 UI
tvResult.text = result
}
// 解析 XML 的函数
private fun parseXml(inputStream: InputStream): String {
val factory = DocumentBuilderFactory.newInstance()
val builder = factory.newDocumentBuilder()
val document: Document = builder.parse(inputStream)
// 获取根节点
val documentElement: Element = document.documentElement
val nodeList: NodeList = documentElement.getElementsByTagName("user")
val sb = StringBuilder()
for (i in 0 until nodeList.length) {
val node: Node = nodeList.item(i)
if (node.nodeType == Node.ELEMENT_NODE) {
val userElement = node as Element
val id = userElement.getElementsByTagName("id").item(0).textContent
val name = userElement.getElementsByTagName("name").0).textContent
val email = userElement.getElementsByTagName("email").item(0).textContent
sb.append("用户ID: $id\n")
sb.append("姓名: $name\n")
sb.append("邮箱: $email\n")
sb.append("---------------------\n")
}
}
return sb.toString()
}
}
}
使用 Retrofit (现代、推荐的方式)
Retrofit 是一个由 Square 公司开发的类型安全的 HTTP 客户端,它能极大地简化网络请求,特别是配合 OkHttp 和 Gson (或其他转换器) 使用时。
步骤 1: 添加依赖
在 app/build.gradle.kts (或 build.gradle) 文件中添加以下依赖:
// build.gradle.kts (Kotlin DSL)
dependencies {
// Retrofit for networking
implementation("com.squareup.retrofit2:retrofit:2.9.0")
// Converter for parsing XML
implementation("com.squareup.retrofit2:converter-simplexml:2.9.0")
// OkHttp (Retrofit uses it internally)
implementation("com.squareup.okhttp3:okhttp:4.11.0")
// For running coroutines on Android main thread
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
}
// build.gradle (Groovy DSL)
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
}
步骤 2: 添加网络权限
同方式一,在 AndroidManifest.xml 中添加 INTERNET 权限。

步骤 3: 创建数据模型类
你需要创建一个 Kotlin 数据类,其结构与服务器返回的 XML 相对应。SimpleXMLConverter 会自动进行映射。
import org.simpleframework.xml.Element
import org.simpleframework.xml.ElementList
import org.simpleframework.xml.Root
// Root 注解对应 XML 的根节点 <users>
@Root(name = "users", strict = false) // strict = false 允许有未知标签
data class UserResponse(
// ElementList 注解对应 <users> 标签下的所有 <user> 标签
// entry = "user" 指定列表中每个元素的标签名
@field:ElementList(entry = "user", inline = true)
var users: List<User>? = null
)
// User 类对应 <user> 标签
data class User(
@field:Element(name = "id") // name 指定对应的 XML 标签名
var id: Int = 0,
@field:Element(name = "name")
var name: String = "",
@field:Element(name = "email")
var email: String = ""
)
步骤 4: 创建 Retrofit API 接口
定义一个接口来描述你的 API 请求。
import retrofit2.Call
import retrofit2.http.GET
interface ApiService {
// @GET 注解表示这是一个 GET 请求
// "users.xml" 是 API 的相对路径
@GET("users.xml")
fun getUsers(): Call<UserResponse>
}
步骤 5: 执行请求并处理结果
在 Activity 或 ViewModel 中使用 Retrofit 发起请求,这里我们使用 lifecycleScope 和 coroutines 来处理异步,这是现代 Android 开发的最佳实践。
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.simpleframework.xml.convert.Registry
import org.simpleframework.xml.convert.RegistryStrategy
import org.simpleframework.xml.core.Persister
import retrofit2.Retrofit
import retrofit2.converter.simplexml.SimpleXmlConverterFactory
class RetrofitActivity : AppCompatActivity() {
private lateinit var tvResult: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) // 假设你有一个布局文件
tvResult = findViewById(R.id.tvResult)
val btnFetch: Button = findViewById(R.id.btnFetch)
btnFetch.setOnClickListener {
fetchUsersWithRetrofit()
}
}
private fun fetchUsersWithRetrofit() {
// lifecycleScope.launch 会在 Activity/Fragment 销毁时自动取消协程
lifecycleScope.launch {
// 在 IO 线程执行网络请求
val result = withContext(Dispatchers.IO) {
try {
// 1. 创建 Retrofit 实例
val retrofit = Retrofit.Builder()
.baseUrl("https://your-server.com/path/to/") // 必须以 /
.addConverterFactory(createSimpleXmlConverterFactory())
.build()
// 2. 创建 API 接口的实例
val apiService = retrofit.create(ApiService::class.java)
// 3. 发起同步请求 (在 withContext 内部是安全的)
val response = apiService.getUsers().execute()
// 4. 检查响应是否成功
if (response.isSuccessful) {
response.body()?.users?.joinToString("\n") { user ->
"ID: ${user.id}, Name: ${user.name}, Email: ${user.email}"
} ?: "Empty response"
} else {
"Error: ${response.code()} ${response.message()}"
}
} catch (e: Exception) {
e.printStackTrace()
"Error: ${e.message}"
}
}
// 5. 在主线程更新 UI
tvResult.text = result
}
}
// 为了解决 SimpleXML 的命名空间问题,有时需要自定义 Persister
private fun createSimpleXmlConverterFactory(): SimpleXmlConverterFactory {
val registry = Registry()
registry.bind(User::class.java, UserConverter())
// 可以继续绑定其他需要的类
val strategy = RegistryStrategy(registry)
val persister = Persister(strategy)
return SimpleXmlConverterFactory.create(persister)
}
}
// 如果你的 XML 有命名空间或者需要更复杂的解析,可以创建自定义 Converter
// 对于简单示例,可以省略这个类
class UserConverter : Converter<User> {
// ... 实现转换逻辑 ...
}
总结与对比
| 特性 | HttpURLConnection |
Retrofit |
|---|---|---|
| 依赖 | 无需添加,Android 原生 | 需要添加 retrofit, okhttp, converter 等库 |
| 易用性 | 较低,需要手动处理连接、流、解析等 | 极高,注解驱动,代码简洁 |
| 类型安全 | 弱,手动解析容易出错 | 强,通过接口和数据模型保证类型安全 |
| 异步处理 | 需要自己实现(如 AsyncTask, Handler) |
优秀,天然支持 Call/Callback、Coroutines、RxJava |
| 功能扩展 | 有限 | 强大,支持拦截器、适配器、多种数据格式转换(JSON, XML, Protobuf等) |
| 适用场景 | 学习网络原理、轻量级、无依赖需求 | 几乎所有现代 Android App,特别是复杂项目 |
强烈建议:在新的 Android 项目中,优先选择 Retrofit 的方式,它能让你更专注于业务逻辑,而不是繁琐的网络操作细节,对于初学者,理解 HttpURLConnection 的工作原理也是有价值的。
