如何在基于Jetpack Compose的安卓钱包中自动检测支付完成
交易状态自动同步方案(Jetpack Compose + Kotlin)
针对你用固定10秒轮询获取交易状态的痛点,推荐以下几种更高效的实现方式,适配Jetpack Compose的状态管理体系:
1. 服务器主动推送(Webhook + 消息推送)
这是最优解,完全替代轮询。让后端在交易状态变更时,主动向你的App推送状态更新:
- 集成FCM或者自定义推送服务,后端通过推送渠道发送交易状态变更通知。
- 在App的推送接收器中解析状态数据,更新本地交易记录,同时通过
StateFlow将状态同步到Compose UI。 - ViewModel层示例代码:
class TransactionViewModel : ViewModel() { private val _transactionState = MutableStateFlow<TransactionState>(TransactionState.Loading) val transactionState: StateFlow<TransactionState> = _transactionState // 接收推送后的状态更新 fun updateTransactionState(newState: TransactionState) { _transactionState.value = newState } }
- Compose UI层通过
collectAsState()自动响应状态变化:
@Composable fun TransactionStatusScreen(viewModel: TransactionViewModel = viewModel()) { val state by viewModel.transactionState.collectAsState() when(state) { is TransactionState.Success -> Text("交易成功") is TransactionState.Failed -> Text("交易失败") TransactionState.Loading -> CircularProgressIndicator() } }
2. WebSocket长连接
保持App与服务器的实时双向连接,交易状态变化时服务器主动推送消息:
- 用OkHttp实现WebSocket客户端,在ViewModel中管理连接生命周期,避免内存泄漏。
- 将收到的状态更新通过
StateFlow传递给UI层,同时处理连接断开后的重连逻辑。 - 核心代码示例:
class TransactionViewModel : ViewModel() { private val _transactionState = MutableStateFlow<TransactionState>(TransactionState.Loading) val transactionState: StateFlow<TransactionState> = _transactionState private var webSocket: WebSocket? = null fun connectWebSocket(transactionId: String) { val request = Request.Builder().url("wss://your-server.com/transactions/$transactionId").build() webSocket = OkHttpClient().newWebSocket(request, object : WebSocketListener() { override fun onMessage(webSocket: WebSocket, text: String) { val state = parseTransactionState(text) // 解析服务器返回的JSON viewModelScope.launch { _transactionState.emit(state) } } }) } override fun onCleared() { webSocket?.close(1000, "ViewModel cleared") super.onCleared() } }
3. 优化轮询方案(迫不得已时使用)
如果暂时无法改造后端,可将固定间隔轮询改为指数退避轮询,减少无效请求:
- 用WorkManager实现后台轮询,设置初始间隔10秒,之后每次翻倍(20s、40s...),直到获取到最终状态(成功/失败)或达到最大重试次数。
- 在ViewModel中监听WorkManager的任务结果,更新UI状态。
- 核心配置:
fun scheduleTransactionPoll(transactionId: String, context: Context) { val workRequest = PeriodicWorkRequestBuilder<PollTransactionWorker>(10, TimeUnit.SECONDS) .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, TimeUnit.SECONDS) .addTag("poll_transaction_$transactionId") .build() WorkManager.getInstance(context).enqueueUniquePeriodicWork( "poll_transaction_$transactionId", ExistingPeriodicWorkPolicy.REPLACE, workRequest ) }
关键注意事项
- 无论用哪种方案,都要确保交易状态的最终一致性:如果推送或WebSocket消息丢失,可在App启动时触发一次主动查询。
- 在Compose中避免直接在UI层处理网络请求,所有状态更新逻辑都放在ViewModel或Repository中,保证UI的可组合性和测试性。
内容的提问来源于stack exchange,提问作者Salty
相关产品推荐
相关产品推荐

