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实现

使用Compose构建响应式UI界面。

  • Name
    UI特点
    Type
    features
    Description
    • 加载状态展示
    • 错误提示
    • 列表展示
    • 下拉刷新

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("重试")
                        }
                    }
                }
            }
        }
    }
}

这篇文章对你有用吗?