
1. Android网络请求基础与权限配置在Android开发中网络请求是实现应用与服务器交互的核心功能。不同于其他平台Android对网络操作有着特殊的安全要求和性能考量。我们先从最基础的权限配置开始讲起。1.1 必备权限声明每个需要网络访问的Android应用都必须在AndroidManifest.xml中声明以下两个基础权限uses-permission android:nameandroid.permission.INTERNET / uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE /这两个权限属于普通权限(normal permission)意味着安装时自动授予无需运行时请求不会出现在权限管理界面用户无法手动撤销注意即使你的应用targetSdkVersion设置为23这两个权限也无需动态请求。这是Android系统对网络基础功能的特殊处理。1.2 网络状态检测ACCESS_NETWORK_STATE权限允许我们检测当前网络连接状态这在现代移动应用中至关重要。通过ConnectivityManager可以获取详细的网络信息val connectivityManager getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val activeNetwork connectivityManager.activeNetwork val networkCapabilities connectivityManager.getNetworkCapabilities(activeNetwork) val isConnected networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET) ?: false val isWifi networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ?: false val isCellular networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ?: false这种检测方式比传统的NetworkInfo API更准确特别是在Android 10及以上版本。1.3 网络安全配置从Android 7.0开始系统默认只信任系统预装的CA证书。如果你的应用需要访问使用自签名证书的服务器必须配置网络安全策略创建res/xml/network_security_config.xml文件network-security-config domain-config domain includeSubdomainstrueyourdomain.com/domain trust-anchors certificates srcraw/your_cert/ /trust-anchors /domain-config /network-security-config在AndroidManifest.xml中引用application android:networkSecurityConfigxml/network_security_config ... 对于调试版本可以配置允许明文通信和调试证书network-security-config debug-overrides trust-anchors certificates srcsystem/ /trust-anchors /debug-overrides base-config cleartextTrafficPermittedtrue trust-anchors certificates srcsystem/ /trust-anchors /base-config /network-security-config2. 主流HTTP客户端对比与选型Android平台提供了多种HTTP客户端实现开发者需要根据项目需求选择合适的工具。以下是主流方案的深度对比2.1 原生HttpsURLConnection作为Android内置的HTTP客户端HttpsURLConnection是最轻量级的选择优点无需额外依赖库支持TLS 1.2/1.3自动处理Cookie和重定向内置响应缓存典型用法val url URL(https://api.example.com/data) val connection url.openConnection() as HttpsURLConnection try { connection.requestMethod GET connection.connectTimeout 10000 connection.readTimeout 15000 if (connection.responseCode HttpURLConnection.HTTP_OK) { val inputStream BufferedInputStream(connection.inputStream) val result inputStream.bufferedReader().use { it.readText() } // 处理结果 } } finally { connection.disconnect() }2.2 OkHttp现代HTTP客户端Square公司的OkHttp已成为Android生态的事实标准核心优势连接池减少延迟透明的GZIP压缩响应缓存自动重试和故障转移基础配置val client OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS) .addInterceptor(HttpLoggingInterceptor().apply { level if (BuildConfig.DEBUG) BODY else NONE }) .cache(Cache( File(context.cacheDir, http_cache), 10L * 1024 * 1024 // 10MB )) .build()2.3 Retrofit类型安全的REST客户端Retrofit构建在OkHttp之上通过接口定义简化API调用典型实现interface ApiService { GET(users/{id}) suspend fun getUser(Path(id) id: String): User POST(users) suspend fun createUser(Body user: User): ResponseUnit Multipart POST(upload) suspend fun uploadFile( Part file: MultipartBody.Part, Part(description) description: RequestBody ): UploadResult } val retrofit Retrofit.Builder() .baseUrl(https://api.example.com/) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() val apiService retrofit.create(ApiService::class.java)2.4 Ktor纯Kotlin的异步客户端来自JetBrains的Ktor适合协程优先的项目特点完全基于Kotlin协程多平台支持灵活的插件系统使用示例val client HttpClient(CIO) { install(JsonFeature) { serializer KotlinxSerializer() } engine { requestTimeout 15000 } } suspend fun fetchUser(id: String): User { return client.get(https://api.example.com/users/$id) }3. 网络请求架构设计与最佳实践3.1 Repository模式实现合理的架构设计能显著提升网络层的可维护性class UserRepository( private val apiService: ApiService, private val cache: Cache ) { private val userCache mutableMapOfString, User() suspend fun getUser(id: String): ResultUser withContext(Dispatchers.IO) { try { // 先检查内存缓存 userCache[id]?.let { returnwithContext Result.success(it) } // 再检查磁盘缓存 val cached cache.getUser(id) if (cached ! null) { userCache[id] cached returnwithContext Result.success(cached) } // 最后请求网络 val user apiService.getUser(id) cache.saveUser(id, user) userCache[id] user Result.success(user) } catch (e: Exception) { Result.failure(e) } } }3.2 ViewModel中的网络调用在ViewModel中正确处理网络请求的生命周期class UserViewModel( private val userRepository: UserRepository ) : ViewModel() { private val _userState MutableStateFlowResultUser?(null) val userState: StateFlowResultUser? _userState fun fetchUser(id: String) { viewModelScope.launch { _userState.value Result.loading() _userState.value userRepository.getUser(id) } } }3.3 离线优先策略现代移动应用应该优先考虑离线体验实现本地缓存层使用Room或DataStore持久化数据实现智能同步机制Database(entities [User::class], version 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao } Dao interface UserDao { Insert(onConflict OnConflictStrategy.REPLACE) suspend fun insert(user: User) Query(SELECT * FROM user WHERE id :id) suspend fun getById(id: String): User? } class CachedUserRepository( private val apiService: ApiService, private val userDao: UserDao ) { suspend fun getUser(id: String): User { val local userDao.getById(id) if (local ! null) { // 后台刷新 viewModelScope.launch { try { val remote apiService.getUser(id) userDao.insert(remote) } catch (e: Exception) { // 静默失败 } } return local } val remote apiService.getUser(id) userDao.insert(remote) return remote } }4. 高级主题与性能优化4.1 多部分文件上传实现高效的文件上传需要考虑多个方面fun uploadFile(file: File, description: String): UploadResult { val requestBody file.asRequestBody(image/*.toMediaType()) val part MultipartBody.Part.createFormData( file, file.name, requestBody ) val descPart description.toRequestBody(text/plain.toMediaType()) return apiService.uploadFile(part, descPart) } // 进度监听扩展 fun RequestBody.withProgress( progressListener: (bytesWritten: Long, contentLength: Long) - Unit ): RequestBody { return object : RequestBody() { override fun contentType() thiswithProgress.contentType() override fun contentLength() thiswithProgress.contentLength() override fun writeTo(sink: BufferedSink) { val countingSink object : ForwardingSink(sink) { var bytesWritten 0L override fun write(source: Buffer, byteCount: Long) { super.write(source, byteCount) bytesWritten byteCount progressListener(bytesWritten, contentLength()) } } thiswithProgress.writeTo(countingSink.buffer()) } } }4.2 请求优先级与取消合理管理请求优先级和生命周期// 定义优先级 enum class RequestPriority { LOW, MEDIUM, HIGH } // 自定义Interceptor class PriorityInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request chain.request() val priority request.tag(RequestPriority::class.java) ?: RequestPriority.MEDIUM return when (priority) { RequestPriority.LOW - { Thread.sleep(200) // 模拟低优先级延迟 chain.proceed(request) } RequestPriority.HIGH - { // 可以在这里修改请求参数 chain.proceed(request.newBuilder() .header(X-Priority, high) .build()) } else - chain.proceed(request) } } } // 使用示例 val request Request.Builder() .url(https://api.example.com/data) .tag(RequestPriority::class.java, RequestPriority.HIGH) .build()4.3 DNS优化与HTTP/2提升网络连接效率的关键技术val client OkHttpClient.Builder() .dns(Dns.SYSTEM) // 可以替换为自定义DNS实现 .protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1)) .connectionSpecs(listOf( ConnectionSpec.MODERN_TLS, // 支持HTTP/2和TLS 1.3 ConnectionSpec.CLEARTEXT // 用于调试 )) .build() // 自定义DNS解析 class CustomDns : Dns { override fun lookup(hostname: String): ListInetAddress { return try { // 可以在这里实现DNS缓存或自定义解析逻辑 Dns.SYSTEM.lookup(hostname) } catch (e: Exception) { // 备用解析方案 listOf(InetAddress.getByName(8.8.8.8)) } } }5. 调试与问题排查5.1 网络请求日志配置详细的请求日志拦截器class CustomLoggingInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request chain.request() val startTime System.nanoTime() logger.debug(-- ${request.method} ${request.url}) request.headers.forEach { name, value - logger.debug($name: $value) } val response try { chain.proceed(request) } catch (e: Exception) { logger.error(-- HTTP FAILED: $e) throw e } val endTime System.nanoTime() logger.debug(-- ${response.code} ${response.message} ${response.request.url} (${(endTime - startTime) / 1e6}ms)) response.headers.forEach { name, value - logger.debug($name: $value) } return response } }5.2 常见问题解决方案Cleartext HTTP traffic not permitted解决方案在AndroidManifest中添加android:usesCleartextTraffictrue或配置网络安全策略Certificate pinning失败检查服务器证书是否变更调试时可以使用CertificatePinner.Builder().add(domain.com, sha256/...).build()SocketTimeoutException适当增加超时时间检查服务器响应速度实现重试机制ProtocolException: Unexpected status line通常是因为服务器返回了非标准HTTP响应可以使用curl -v检查原始响应缓存失效问题确保Cache-Control头正确设置检查OkHttp缓存配置考虑使用ETag或Last-Modified头5.3 性能监控工具Android Profiler的网络监控Charles或Fiddler抓包工具OkHttp的事件监听器val client OkHttpClient.Builder() .eventListener(object : EventListener() { override fun callStart(call: Call) { super.callStart(call) // 记录开始时间 } override fun callEnd(call: Call) { super.callEnd(call) // 计算总耗时 } override fun dnsStart(call: Call, domainName: String) { super.dnsStart(call, domainName) // 记录DNS查询开始 } }) .build()6. 现代Android网络开发趋势6.1 协程与Flow集成Kotlin协程彻底改变了Android异步编程class UserRepository Inject constructor( private val apiService: ApiService, private val cache: UserCache ) { fun getUserStream(id: String): FlowResultUser flow { // 先发射缓存数据 cache.getUser(id)?.let { emit(Result.success(it)) } try { // 请求网络 val user apiService.getUser(id) cache.saveUser(id, user) emit(Result.success(user)) } catch (e: Exception) { emit(Result.failure(e)) } }.flowOn(Dispatchers.IO) }6.2 GraphQL集成现代API设计趋势interface GraphQLService { POST(graphql) suspend fun query( Body request: GraphQLRequest ): GraphQLResponse } data class GraphQLRequest( val query: String, val variables: MapString, Any? null ) data class GraphQLResponse( val data: JsonObject?, val errors: ListGraphQLError? ) // 使用示例 val query query GetUser($id: ID!) { user(id: $id) { id name email } } .trimIndent() val response graphQLService.query( GraphQLRequest(query, mapOf(id to 123)) )6.3 WebSocket实时通信实现实时数据更新val webSocketClient OkHttpClient() val request Request.Builder() .url(wss://echo.websocket.org) .build() val listener object : WebSocketListener() { override fun onOpen(webSocket: WebSocket, response: Response) { webSocket.send(Hello, Server!) } override fun onMessage(webSocket: WebSocket, text: String) { logger.debug(Received: $text) } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { webSocket.close(1000, null) } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { logger.error(WebSocket error, t) } } webSocketClient.newWebSocket(request, listener)6.4 多模块项目中的网络层设计对于大型项目推荐采用分层设计:network模块 - 包含所有网络相关代码Retrofit接口数据转换器拦截器错误处理:data模块 - 实现Repository组合网络和本地数据源业务逻辑转换:app模块 - 提供依赖创建OkHttpClient单例配置基础URL管理认证状态// network模块中的Service internal interface InternalApiService { GET(internal/users/{id}) suspend fun getInternalUser(Path(id) id: String): InternalUserDto } // data模块中的Repository class UserRepository Inject constructor( private val apiService: InternalApiService, private val mapper: UserMapper ) { suspend fun getUser(id: String): User { return mapper.map(apiService.getInternalUser(id)) } }