ComposeUI中的网络请求最佳实践
纯想的APIKEY: e1300567e653b2e517e66f609d006e42
AndroidManifest.xml
里添加:
<uses-permission android:name="android.permission.INTERNET" />
允许 http 访问,添加network-security-config.xml
:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
并在 application
标签里添加:
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
HTTP协议发展史
HTTP协议经历了多个版本的演进,从最初的0.9到现在的HTTP/3。
- Name
发展历程
- Type
- history
- Description
- HTTP/0.9(1991): 仅支持GET方法,纯文本传输
- HTTP/1.0(1996): 增加POST等方法,支持多媒体a
- HTTP/1.1(1997): 持久连接,管道机制
- HTTP/2(2015): 多路复用,服务器推送
- HTTP/3(2022): 基于QUIC协议,更快更安全
- Name
核心特性
- Type
- features
- Description
- 无状态性: 每次请求相互独立
- 可扩展性: 自定义头部字段
- 可靠性: 基于TCP/IP协议
- 简单性: 人类可读的文本格式
HTTP基础概念
// HTTP请求的组成部分
struct HTTPComponents {
// 请求行
let method: String // 请求方法
let path: String // 资源路径
let version: String // 协议版本
// 请求头
var headers: [String: String] = [
"Accept": "*/*",
"User-Agent": "SwiftUI/1.0"
]
// 请求体
var body: Data?
}
现代网络请求架构
在Compose应用中实现简单高效的网络请求。
- Name
设计原则
- Type
- principles
- Description
- 简单直接: 避免过度封装
- 协程支持: 异步操作更简单
- 状态管理: 使用StateFlow
- 错误处理: try-catch机制
ViewModel实现
class ArticleViewModel : ViewModel() {
private val client = OkHttpClient()
private val json = Json { ignoreUnknownKeys = true }
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow()
init {
fetchArticles()
}
fun fetchArticles() {
viewModelScope.launch {
_uiState.value = UiState.Loading
try {
val request = Request.Builder()
.url("https://api.example.com/articles")
.build()
withContext(Dispatchers.IO) {
val response = client.newCall(request).execute()
if (!response.isSuccessful) {
throw Exception("请求失败: ${response.code}")
}
val articles = json.decodeFromString<List<Article>>(
response.body?.string() ?: ""
)
_uiState.value = UiState.Success(articles)
}
} catch (e: Exception) {
_uiState.value = UiState.Error(e.message ?: "未知错误")
}
}
}
}
// UI状态
sealed class UiState {
object Loading : UiState()
data class Success(val articles: List<Article>) : UiState()
data class Error(val message: String) : UiState()
}
// 数据模型
@Serializable
data class Article(
val id: Int,
val title: String,
val content: String
)
Compose UI实现
@Composable
fun ArticleListScreen(
viewModel: ArticleViewModel = viewModel()
) {
val uiState by viewModel.uiState.collectAsState()
Scaffold(
topBar = {
TopAppBar(title = { Text("文章列表") })
}
) { padding ->
when (val state = uiState) {
is UiState.Loading -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
is UiState.Success -> {
LazyColumn(
contentPadding = padding
) {
items(state.articles) { article ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = article.title,
style = MaterialTheme.typography.h6
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = article.content,
style = MaterialTheme.typography.body1
)
}
}
}
}
}
is UiState.Error -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(state.message)
Button(
onClick = { viewModel.fetchArticles() }
) {
Text("重试")
}
}
}
}
}
}
}