Offline Queue — är en mekanism som sparar användaroperationer lokalt när enheten är offline och skickar dem till servern när anslutningen återställs. Utan en offlinekö förlorar användaren alla åtgärder som utförts utan internet, vilket är oacceptabelt i mobilapplikationer. Enligt Google Developers (2025) ökar implementeringen av offline-first-arkitektur användarbehållningen med 30% i regioner med instabilt internet.
Huvudpunkter
Offline Queue — är en ordnad samling operationer (skapa, uppdatera, ta bort) som applikationen lagrar lokalt när enheten inte har nätverksåtkomst. När anslutningen återställs skickar kön operationerna till servern i samma ordning som användaren utförde dem.
Föreställ dig ett scenario: en användare av en meddelandeapp skriver meddelanden i tunnelbanan utan internet. Varje tryck på “Skicka” läggs till i Offline Queue. När tåget kommer ut ur tunneln och nätverket visas skickas alla meddelanden automatiskt. Användarupplevelsen — sömlös: användaren märker inte att den var offline, förutom en liten fördröjning vid sändning.
Enligt Uber Engineering (2024) bearbetar deras offlinekö över 2 miljoner operationer per dag i regioner med låg anslutningskvalitet. Kön använder lokal Room-lagring med FIFO-ordning och en mekanism för garanterad leverans exactly-once.
data class QueuedOperation(
val id: String,
val type: OperationType,
val endpoint: String,
val payload: String,
val timestamp: Long,
val retryCount: Int = 0,
val idempotencyKey: String
)
Varje operation innehåller all data som behövs för återsändning: endpoint, förfrågans brödtext, tidsstämpel och idempotencyKey. Room-DB garanterar att kön bevaras vid applikationsomstart och OS-fel.
Leveransgaranti — könens huvuduppgift. Användaren måste vara säker på att dess åtgärd (skicka meddelande, gilla, beställa) kommer att utföras, även om nätverket inte är tillgängligt vid utförandetillfället. Offline Queue med retry-mekanism säkerställer leverans eventually.
Förbättrad UX vid dålig anslutning — enligt GSMA Mobile Economy Report (2025) har cirka 40% av mobilanvändarna i världen instabil internetanslutning. Offline Queue gör appen användbar i tunnelbanor, hissar, avlägsna områden — överallt där anslutningen är intermittent.
Minskad dataförlust — utan kö förloras alla åtgärder som utförs offline. Användaren kan fylla i ett långt formulär, trycka på “Skicka” och se ett nätverksfel — all inmatning går förlorad. Offline Queue sparar data och skickar dem vid första tillfället. Auto-save i Google Docs — ett klassiskt exempel på offlinekö för dokument.
Asynkron synkronisering — kön gör att applikationen inte blockerar UI:t under sändning. Användaren fortsätter att arbeta medan synkroniseringshanteraren bearbetar kön i bakgrunden. Detta överensstämmer med principerna för Reactive Architecture och förbättrar gränssnittets responsivitet.
Tre lager av kön: lagring (persistence), schemaläggare (scheduler) och processor (executor). Lagring — Room med tabell QueuedOperation. Schemaläggare — WorkManager (Android) eller BGTaskScheduler (iOS), som startar synkronisering när nätverk blir tillgängligt. Processor — sekventiell FIFO-iterator som skickar operationer en i taget.
Bearbetningsordning — kritisk för datakonsistens. Om användaren skapade en post och sedan redigerade den, måste båda operationerna skickas i samma ordning. Annars får servern först en uppdatering av en post som inte existerar — fel. Sequential FIFO — strikt ordning med beroendekontroll mellan operationer.
Sammanslagningsstrategi — om det finns en CREATE och omedelbart därefter en DELETE av samma objekt i kön, kan båda operationerna tas bort utan sändning: slutligt tillstånd — objektet skapades inte. På samma sätt kan CREATE + UPDATE av samma CREATE slås samman till en CREATE med de senaste uppgifterna. Köoptimering minskar antalet HTTP-förfrågningar och påskyndar synkronisering.
Enligt Android Developers (2025) är WorkManager det föredragna sättet att hantera Offline Queue på Android: det garanterar exekvering även efter enhetsomstart, stöder begränsningar för nätverkstillgänglighet och tillåter inställning av återförsökspolicy via NetworkType.CONNECTED.
class SyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result = runCatching {
queueRepository.processNextBatch(batchSize = 10)
Result.success()
}.getOrDefault(Result.retry())
}
CoroutineWorker bearbetar batchar av operationer och returnerar Result.retry() vid fel — WorkManager återupprepar automatiskt starten med exponentiell fördröjning. Detta är det enklaste sättet att få en pålitlig Offline Queue på Android.
Exponential Backoff — standardstrategi för återförsök med ökande intervall: 2 s, 4 s, 8 s, 16 s och så vidare upp till maxgränsen. Detta förhindrar upprepad överbelastning av servern om den är tillfälligt otillgänglig. Java-biblioteket Resilience4j (2024) tillhandahåller en färdig Retry-implementation med konfigurerbar backoff.
Maximalt antal försök — en kritisk parameter. Om operationen misslyckats efter 5–10 försök är ytterligare försök meningslösa. Rekommenderas är dead letter queue: efter att försöken är slut flyttas operationen till en separat tabell för manuell analys. Enligt Microsoft Patterns & Practices (2024) förenklar dead letter queue felsökning av synkroniseringsproblem och förhindrar att kön blockeras av felaktiga operationer.
Jitter — slumpmässig variation — tillägg av ett slumpmässigt tal till backoff-intervallet. Om tusen enheter samtidigt får nätverk efter en frånkoppling kommer de alla att starta synkronisering samtidigt. Jitter sprider ut dem i tid och förhindrar Cache Stampede på servern. Fullständig jitter: delay = random(0, backoff) — rekommenderas av AWS (2024) för API-klienter.
Last Write Wins (LWW) — den enklaste strategin: vid konflikt vinner operationen med den senare tidsstämpeln. LWW kräver tidssynkronisering — tidsstämpeln måste genereras på servern eller använda Logical Clock (Lamport clocks). Nackdel: en användares data kan skrivas över av en annan användares data utan varning.
OT (Operational Transformation) — algoritm som används av Google Docs och Figma för samarbetsredigering i realtid, inklusive offlineläge. OT omvandlar operationer så att de kan tillämpas på vilket dokumenttillstånd som helst, vilket säkerställer konsistens utan låsning. CRDT (Conflict-Free Replicated Data Types) — ett alternativ till OT som blir populärt i mobilappar: data är strukturerade så att konflikter kan lösas matematiskt utan central server.
Custom Merge — för applikationer med enkel datamodell (anteckningar, kontakter) kan anpassade sammanslagningsregler implementeras. Till exempel för en anteckning: om texten ändrats i två versioner, slå samman dem som en konkatenering med avgränsare. Användarlöst konflikt — om automatisk sammanslagning inte är möjlig, visa båda versionerna för användaren och låt dem välja. Dropbox (2024) använder detta tillvägagångssätt för konflikter i offlinefiler och skapar kopior med prefix “Conflicted Copy”.
Idempotency Key — unik identifierare för en operation som servern använder för att upptäcka dubblerade förfrågningar. Om klienten skickar samma förfrågan med samma nyckel returnerar servern resultatet av den redan utförda operationen utan att utföra den igen. Detta är kritiskt för Offline Queue där återsändningar är möjliga vid nätverksfel.
Format för idempotency key — UUID eller hash av förfrågeparametrar. Servern måste lagra utförda nycklar tillsammans med resultatet under en viss tid (vanligtvis 24 timmar) för att upptäcka dubbletter. Stripe API (2024) — ett exemplariskt exempel: nyckeln skickas i rubriken Idempotency-Key och upprepade förfrågningar med samma nyckel returnerar cachat svar.
Klientgenerering — nyckeln skapas på klienten innan operationen skickas och sparas i tabellen QueuedOperation. Vid återförsök ändras inte nyckeln. Exactly-once-arkitektur — kombinationen av idempotency key på klienten och deduplicering på servern — det enda sättet att garantera att en operation inte utförs två gånger.
fun createOperation(type: OperationType, payload: String): QueuedOperation =
QueuedOperation(
id = UUID.randomUUID().toString(),
type = type,
endpoint = type.endpoint,
payload = payload,
timestamp = currentTimeMillis(),
idempotencyKey = UUID.randomUUID().toString()
)
Varje operation får två UUID: ett — identifierare för posten i kön, det andra — idempotency key för servern. Serverdeduplicering baserat på idempotencyKey garanterar att även vid återsändning inte beställningen dupliceras.
Vanliga frågor
Cache lagrar datakopior för snabb läsning offline. Offline Queue lagrar användaroperationer för efterföljande skrivning till servern. Cache fungerar för läsning, kön — för skrivning. Båda komponenterna kan samexistera i offline-first-arkitektur.
Rekommenderad gräns — 100–500 operationer. Fler — risk för minnesöversvämning och lång synkronisering vid återställning av nätverk. Vid överskridande av gränsen bör applikationen varna användaren och föreslå prioritering av operationer. Förnuftig begränsning — 50 uppdateringsoperationer + 10 skapandeoperationer.
Operationer äldre än 7 dagar med noll framgång flyttas till dead letter queue. Analysera dem manuellt: kanske har API ändrats och slutpunkten finns inte längre. Automatisk rensning — HealthCheck-uppgift en gång om dagen tar bort eller arkiverar utgångna operationer.
Använd beroendegraf (DAG): varje operation innehåller en lista med parentOperationId som måste slutföras innan den skickas. Room-fråga med ORDER BY parent returnerar operationer i rätt ordning. Kaskadsändning — efter att varje operation slutförts, kontrollera om underordnade operationer har låsts upp.
Använd Network Less Tool i Android Emulator eller Network Link Conditioner i iOS Simulator för att simulera nätverksförlust. Skriv tester som lägger till operationer i kön i offlineläge, återställer anslutningen och kontrollerar att alla operationer har skickats och bearbetats av servern.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också