A transient signal can disappear when nobody is collecting it. Increasing replay may show the confirmation again later, but replay alone does not define whether the user has already handled the outcome.
Model the operation and its result explicitly. Keep an operation ID, reconcile the server's authoritative status, and render pending, confirmed, or failed state. The UI decides how to present that state when active again.
sealed interface PurchaseStatus {
data class Pending(val operationId: String) : PurchaseStatus
data class Confirmed(val receiptId: String) : PurchaseStatus
data class Failed(val reason: String) : PurchaseStatus
}
This model is illustrative; persistent storage and server verification are separate requirements. A local Boolean must not be the authority that unlocks a paid entitlement.
If navigating to a receipt, make repeated handling safe for the same receipt ID. Define acknowledgement separately from the business result: dismissing a confirmation must not erase the purchase itself. On process recreation, recover the operation and reconcile before allowing another charge attempt.
Can we guarantee exactly one navigation across a crash? Presentation and persistence are not one atomic transaction. Prefer a recoverable, idempotent user experience over an unsupported exactly-once claim. Explain the trade-off between occasionally revisiting a receipt and silently losing a successful outcome.
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐