30. Apr. 2025·8 Min. Lesezeit

Offline‑First Hintergrund‑Synchronisation mobiler Apps: Konflikte, Wiederholungen und UX

Plane die Offline‑First‑Hintergrundsynchronisation mobiler Apps mit klaren Konfliktregeln, Wiederholungslogik und einer einfachen UX fĂŒr ausstehende Änderungen in nativen Kotlin‑ und SwiftUI‑Apps.

Offline‑First Hintergrund‑Synchronisation mobiler Apps: Konflikte, Wiederholungen und UX

Das Problem: Nutzer bearbeiten offline und die RealitÀt Àndert sich

Jemand beginnt eine Aufgabe bei guter Verbindung und lĂ€uft dann in einen Fahrstuhl, eine Ecke im Lager oder einen U‑Bahn‑Tunnel. Die App lĂ€uft weiter, also arbeitet die Person weiter. Sie tippt auf Speichern, fĂŒgt eine Notiz hinzu, Ă€ndert einen Status oder erstellt vielleicht sogar einen neuen Datensatz. Auf dem Bildschirm sieht alles sofort korrekt aus.

SpĂ€ter kommt die Verbindung zurĂŒck und die App versucht im Hintergrund aufzuholen. Genau hier kann Hintergrund‑Sync die Leute ĂŒberraschen.

Wenn die App nicht vorsichtig ist, kann dieselbe Aktion zweimal gesendet werden (Duplikate), oder eine neuere Änderung vom Server kann das ĂŒberschreiben, was der Nutzer gerade getan hat (verlorene Änderungen). Manchmal zeigt die App verwirrende ZustĂ€nde wie „Gespeichert“ und „Nicht gespeichert“ gleichzeitig, oder ein Datensatz erscheint, verschwindet und taucht nach der Synchronisation wieder auf.

Ein Konflikt ist simpel: zwei unterschiedliche Änderungen wurden an derselben Sache vorgenommen, bevor die App sie zusammengefĂŒhrt hat. Zum Beispiel Ă€ndert eine Support‑Mitarbeiterin offline die PrioritĂ€t eines Tickets auf Hoch, wĂ€hrend ein Kollege online das Ticket schließt. Wenn das offline GerĂ€t wieder verbindet, können beide Änderungen nicht ohne Regel sauber angewendet werden.

Das Ziel ist nicht, Offline perfekt wirken zu lassen. Das Ziel ist, es vorhersehbar zu machen:

  • Menschen können weiterarbeiten, ohne Angst vor Datenverlust.
  • Die Synchronisation passiert spĂ€ter ohne mysteriöse Duplikate.
  • Wenn etwas Aufmerksamkeit braucht, sagt die App klar, was passiert ist und was zu tun ist.

Das gilt, egal ob du in Kotlin/SwiftUI hand‑codest oder native Apps mit einer No‑Code‑Plattform wie AppMaster baust. Die schwierige Frage ist nicht das UI‑Widget. Sie ist: Wie verhĂ€lt sich die App, wenn sich die Welt Ă€ndert, wĂ€hrend der Nutzer offline ist?

Ein einfaches Offline‑First‑Modell (ohne Fachchinesisch)

Eine Offline‑First‑App geht davon aus, dass das Telefon manchmal die Verbindung verliert; trotzdem soll die App nutzbar bleiben. Bildschirme sollten laden und Buttons funktionieren, auch wenn der Server nicht erreichbar ist.

Vier Begriffe decken das meiste ab:

  • Lokaler Cache: auf dem GerĂ€t gespeicherte Daten, damit die App sofort etwas anzeigen kann.
  • Sync‑Warteschlange: eine Liste von Aktionen, die der Nutzer offline (oder bei schwacher Verbindung) durchgefĂŒhrt hat.
  • Server‑Wahrheit: die Version, die auf dem Backend liegt und die am Ende alle teilen.
  • Konflikt: wenn die wartende Änderung des Nutzers nicht mehr sauber angewendet werden kann, weil sich die Server‑Version geĂ€ndert hat.

Ein nĂŒtzliches Denkmodell ist, Lesen und Schreiben zu trennen.

Lesen ist meist einfach: Zeige die bestmöglichen Daten (oft aus dem lokalen Cache) und aktualisiere ruhig, wenn das Netzwerk zurĂŒck ist.

Schreiben ist anders. Verlasse dich nicht darauf, "den ganzen Datensatz auf einmal zu speichern". Das bricht sofort, sobald du offline bist.

Stattdessen zeichne auf, was der Nutzer getan hat, als kleine EintrĂ€ge in einem Änderungsprotokoll. Zum Beispiel: „Status auf Genehmigt setzen“, „Kommentar X hinzufĂŒgen“, „Menge von 2 auf 3 Ă€ndern“. Jeder Eintrag kommt mit Zeitstempel und ID in die Sync‑Warteschlange. Der Hintergrund‑Sync versucht dann, die EintrĂ€ge zuzustellen.

Der Nutzer kann weiterarbeiten, wĂ€hrend Änderungen von ausstehend zu synchronisiert wechseln.

Wenn du eine No‑Code‑Plattform wie AppMaster verwendest, brauchst du trotzdem dieselben Bausteine: gecachte Lesezugriffe fĂŒr schnelle Bildschirme und eine klare Warteschlange von Nutzeraktionen, die erneut versucht, zusammengefĂŒhrt oder bei Konflikt markiert werden kann.

Entscheide, was wirklich Offline‑UnterstĂŒtzung braucht

Offline‑First kann sich anhören wie „alles funktioniert ohne Verbindung“, aber dieses Versprechen ist hĂ€ufig der Punkt, an dem Apps Probleme bekommen. WĂ€hle die Teile, die wirklich von Offline profitieren, und halte den Rest klar online‑only.

Denk in Nutzerabsicht: Was mĂŒssen Leute im Keller, im Flugzeug oder im Lager mit wechselndem Empfang tun? Eine gute Grundeinstellung ist, Aktionen zu unterstĂŒtzen, die alltĂ€gliche Arbeit erstellen oder aktualisieren, und Aktionen zu blockieren, bei denen die „aktuelle Wahrheit“ wichtig ist.

Praktisch sind oft offline‑freundlich: Erstellen und Bearbeiten von Kern‑DatensĂ€tzen (Notizen, Aufgaben, Inspektionen, Tickets), EntwĂŒrfe von Kommentaren und AnhĂ€ngen von Fotos (lokal gespeichert, spĂ€ter hochgeladen). Löschen kann auch funktionieren, aber sicherer als Soft‑Delete mit einer RĂŒckgĂ€ngig‑Zeit, bis der Server bestĂ€tigt.

Jetzt entscheide, was in Echtzeit bleiben muss, weil das Risiko zu groß ist. Zahlungen, BerechtigungsĂ€nderungen, Genehmigungen und alles mit sensiblen Daten sollten meist eine Verbindung erfordern. Wenn die Aktion ohne ServerprĂŒfung nicht gĂŒltig ist, erlaube sie offline nicht. Zeige eine klare „Verbindung erforderlich“‑Hinweis, nicht eine mysteriöse Fehlermeldung.

Setze Erwartungen zur AktualitĂ€t. „Offline“ ist nicht binĂ€r. Definiere, wie alt Daten sein dĂŒrfen: Minuten, Stunden oder „nĂ€chster App‑Start“. Zeige diese Regel in der UI in klaren Worten, z. B. „Zuletzt aktualisiert vor 2 Stunden“ und „Synchronisiert, wenn online“.

Markiere schließlich daten mit hohem Konfliktrisiko frĂŒh. InventarstĂ€nde, geteilte Aufgaben und Team‑Nachrichten sind typische Konfliktmagneten, weil mehrere Leute schnell daran arbeiten. FĂŒr diese solltest du Offline‑Bearbeitungen auf EntwĂŒrfe beschrĂ€nken oder Änderungen als separate Ereignisse erfassen, statt einen einzelnen Wert zu ĂŒberschreiben.

Wenn du in AppMaster baust, hilft dir dieser Schritt, Daten und GeschĂ€ftsregeln so zu modellieren, dass die App sichere EntwĂŒrfe offline speichert, wĂ€hrend riskante Aktionen online‑only bleiben.

Design der Sync‑Warteschlange: Was du fĂŒr jede Änderung speicherst

Wenn ein Nutzer offline arbeitet, versuche nicht „die Datenbank zu synchronisieren“. Synchronisiere die Aktionen des Nutzers. Eine klare Aktionswarteschlange ist das RĂŒckgrat des Hintergrund‑Sync und bleibt verstĂ€ndlich, wenn etwas schiefgeht.

Halte Aktionen klein und menschlich, passend zu dem, was der Nutzer tatsÀchlich getan hat:

  • Einen Datensatz erstellen
  • Bestimmte Feld(er) aktualisieren
  • Status Ă€ndern (einreichen, genehmigen, archivieren)
  • Löschen (vorzugsweise Soft‑Delete bis zur BestĂ€tigung)

Kleine Aktionen sind leichter zu debuggen. Wenn der Support helfen muss, ist es viel einfacher zu lesen: „Status geĂ€ndert Draft -> Submitted“ als einen riesigen Blob geĂ€nderter JSON‑Daten zu untersuchen.

FĂŒr jede wartende Aktion speichere genug Metadaten, um sie sicher erneut abzuspielen und Konflikte zu erkennen:

  • Datensatz‑Identifier (und eine temporĂ€re lokale ID fĂŒr neu erstellte DatensĂ€tze)
  • Aktions‑Zeitstempel und GerĂ€te‑Identifier
  • Erwartete Version (oder zuletzt bekannte Aktualisierungszeit) des Datensatzes
  • Payload (die konkreten geĂ€nderten Felder, plus alter Wert wenn möglich)
  • Idempotency‑Key (eine eindeutige Aktions‑ID, damit Retries keine Duplikate erzeugen)

Diese erwartete Version ist der SchlĂŒssel zu ehrlicher Konfliktbehandlung. Wenn sich die Server‑Version bewegt hat, kannst du pausieren und um Entscheidung bitten, statt stillschweigend jemand anderen zu ĂŒberschreiben.

Manche Aktionen mĂŒssen zusammen angewendet werden, weil der Nutzer sie als einen Schritt sieht. Zum Beispiel „Bestellung erstellen“ plus „drei Positionen hinzufĂŒgen“ sollten als Einheit gelingen oder ausstehen. Speicher eine Gruppen‑ID (oder Transaktions‑ID), damit die Sync‑Engine sie zusammen senden und entweder alle bestĂ€tigen oder alle pending lassen kann.

Egal ob hĂ€ndisch gebaut oder in AppMaster: Das Ziel ist das gleiche — jede Änderung wird einmal aufgezeichnet, sicher wiedergegeben und ist erklĂ€rbar, wenn etwas nicht passt.

Konfliktlösungsregeln, die du Nutzer:innen erklÀren kannst

Native ausliefern, ohne neu zu schreiben
Nutze native Kotlin‑ und SwiftUI‑Ausgaben, ohne den Source neu schreiben zu mĂŒssen.
Loslegen

Konflikte sind normal. Das Ziel ist nicht, sie unmöglich zu machen, sondern selten, sicher und leicht erklÀrbar zu halten, wenn sie auftreten.

Benenne den Moment, in dem ein Konflikt passiert: die App sendet eine Änderung, und der Server antwortet: „Dieser Datensatz ist nicht die Version, die du bearbeitet hast.“ Deshalb ist Versionierung wichtig.

Behalte zwei Werte bei jedem Datensatz:

  • Server‑Version (die aktuelle Version auf dem Server)
  • Erwartete Version (die Version, die das Telefon beim Bearbeiten gesehen hat)

Wenn die erwartete Version ĂŒbereinstimmt, akzeptiere das Update und erhöhe die Server‑Version. Wenn nicht, wende deine Konfliktregel an.

WĂ€hle pro Datentyp eine Regel (nicht eine Regel fĂŒr alles)

Verschiedene Daten brauchen verschiedene Regeln. Ein Statusfeld ist nicht dasselbe wie eine lange Notiz.

Regeln, die Nutzer meist verstehen:

  • Last write wins: okay fĂŒr niedriges Risiko, z. B. Anzeige‑Einstellungen.
  • Felder mergen: gut, wenn Felder unabhĂ€ngig sind (Status vs Notizen).
  • Nutzer fragen: am besten bei risikoreichen Änderungen wie Preis, Berechtigungen oder Summen.
  • Server gewinnt, aber mit Kopie: behalte den Server‑Wert, speichere die NutzerĂ€nderung als Entwurf, den sie wieder anwenden können.

In AppMaster lassen sich diese Regeln gut als visuelle Logik abbilden: Versionen prĂŒfen, Felder vergleichen und dann den Pfad wĂ€hlen.

Entscheide, wie Löschen sich verhÀlt (sonst verlierst du Daten)

Löschen ist der knifflige Fall. Verwende ein Tombstone (ein „deleted“‑Marker) statt den Datensatz sofort zu entfernen. Dann entscheide, was passiert, wenn jemand einen Datensatz bearbeitet, der anderswo gelöscht wurde.

Eine klare Regel ist: „Deletes gewinnen, aber man kann wiederherstellen.“ Beispiel: Ein VerkĂ€ufer bearbeitet offline eine Kundennotiz, wĂ€hrend ein Admin diesen Kunden löscht. Bei Sync zeigt die App: „Kunde wurde gelöscht. Wiederherstellen, um deine Notiz anzuwenden?“ So vermeidest du stillen Verlust und gibst Kontrolle an die Nutzerin zurĂŒck.

Wiederholungen und FehlerzustÀnde: mach es vorhersehbar

Wenn Sync fehlschlĂ€gt, kĂŒmmern sich die meisten Nutzer nicht um die Ursache. Sie wollen wissen, ob ihre Arbeit sicher ist und was als NĂ€chstes passiert. Ein vorhersehbares Zustandsmodell verhindert Panik und Tickets beim Support.

Beginne mit einem kleinen, sichtbaren Statusmodell und nutze es konsistent auf allen Bildschirmen:

  • Queued: auf dem GerĂ€t gespeichert, wartet auf Netzwerk
  • Syncing: wird gerade gesendet
  • Sent: vom Server bestĂ€tigt
  • Failed: konnte nicht gesendet werden, wird wiederholt oder braucht Aufmerksamkeit
  • Needs review: gesendet, aber vom Server abgelehnt oder markiert

Retries sollten schonend fĂŒr Akku und Daten sein. Verwende anfĂ€nglich schnelle Wiederholungen (fĂŒr kurze SignalabbrĂŒche), dann verlangsame sie. Ein einfacher Backoff wie 1 Min, 5 Min, 15 Min, dann stĂŒndlich ist leicht verstĂ€ndlich. Wiederhole außerdem nur, wenn es Sinn macht (versuche nicht, eine ungĂŒltige Änderung endlos zu senden).

Behandle Fehlerarten unterschiedlich, weil die nÀchste Aktion unterschiedlich ist:

  • Offline / kein Netzwerk: bleibe in der Warteschlange, wiederhole bei Online
  • Timeout / Server nicht verfĂŒgbar: markiere als fehlgeschlagen, automatische Wiederholung mit Backoff
  • Auth abgelaufen: pausiere Sync und bitte den Nutzer, sich erneut anzumelden
  • Validierung fehlgeschlagen (falsche Eingaben): braucht ÜberprĂŒfung, zeige, was zu korrigieren ist
  • Konflikt (Datensatz geĂ€ndert): braucht ÜberprĂŒfung, leite gemĂ€ĂŸ deiner Konfliktregeln

Idempotenz macht Retries sicher. Jede Änderung sollte eine eindeutige Aktions‑ID (oft eine UUID) haben, die mit der Anfrage gesendet wird. Wenn die App dieselbe Änderung erneut sendet, sollte der Server die ID erkennen und dasselbe Ergebnis zurĂŒckgeben, statt Duplikate zu erzeugen.

Beispiel: Ein Techniker speichert einen abgeschlossenen Auftrag offline und fĂ€hrt dann in einen Aufzug. Die App sendet das Update, es time‑outet und wird spĂ€ter erneut versucht. Mit einer Aktions‑ID ist der zweite Send harmlos. Ohne sie erzeugst du vielleicht doppelte „abgeschlossen“‑Ereignisse.

In AppMaster behandle diese ZustĂ€nde und Regeln als erstklassige Felder und Logik in deinem Sync‑Prozess, damit deine Kotlin‑ und SwiftUI‑Apps ĂŒberall gleich reagieren.

UX fĂŒr ausstehende Änderungen: was der Nutzer sieht und tun kann

Konflikte vorhersehbar machen
FĂŒge VersionsprĂŒfungen und Konfliktregeln als klare, testbare GeschĂ€ftsprozesse hinzu.
Jetzt bauen

Menschen sollen sich sicher fĂŒhlen, die App offline zu nutzen. Gute „Pending changes“‑UX ist ruhig und vorhersehbar: Sie bestĂ€tigt, dass Arbeit auf dem GerĂ€t gespeichert ist, und macht den nĂ€chsten Schritt offensichtlich.

Ein dezenter Indikator ist besser als ein Warnbanner. Zeige z. B. ein kleines „Synchronisiere“‑Icon in der Kopfleiste oder ein unaufdringliches „3 ausstehend“‑Label auf dem Bildschirm, wo die Änderungen passieren. Spare auffĂ€llige Farben fĂŒr echte Gefahren (z. B. „kann nicht hochgeladen werden, weil du abgemeldet bist").

Gib den Nutzern einen Ort, an dem sie alles verstehen können. Ein simples Outbox‑ oder Ausstehende‑Änderungen‑Fenster kann EintrĂ€ge mit klarer Sprache auflisten wie „Kommentar zu Ticket 104 hinzugefĂŒgt“ oder „Profilfoto aktualisiert“. Diese Transparenz verhindert Panik und reduziert Support‑Anfragen.

Was Nutzer tun können

Die meisten Menschen brauchen nur wenige Aktionen, die ĂŒberall konsistent sein sollten:

  • Jetzt erneut versuchen
  • Nochmals bearbeiten (erstellt eine neue Änderung)
  • Lokale Änderung verwerfen
  • Details kopieren (nĂŒtzlich beim Melden eines Problems)

Halte Statuslabels einfach: Pending, Syncing, Failed. Wenn etwas fehlschlĂ€gt, erklĂ€re es wie ein Mensch: „Konnte nicht hochladen. Kein Internet.“ oder „Abgelehnt, weil dieser Datensatz von jemand anderem geĂ€ndert wurde.“ Vermeide Fehlercodes.

Blockiere nicht die ganze App

Blockiere nur Aktionen, die wirklich online sein mĂŒssen, wie „Mit Stripe bezahlen“ oder „neuen Nutzer einladen“. Alles andere sollte weiter funktionieren, inklusive dem Anzeigen kĂŒrzlich geladener Daten und dem Erstellen neuer EntwĂŒrfe.

Ein realistischer Ablauf: Ein Field‑Tech bearbeitet einen Bericht im Keller. Die App zeigt „1 ausstehend“ und lĂ€sst ihn weiterarbeiten. SpĂ€ter wechselt der Status zu „Synchronisiere“ und leert sich automatisch. Wenn es fehlschlĂ€gt, bleibt der Bericht verfĂŒgbar, markiert als „Fehlgeschlagen“, mit einem einzigen Button „Jetzt erneut“.

Wenn du in AppMaster baust, modelliere diese ZustĂ€nde als Teil jedes Datensatzes (pending, failed, synced), damit die UI sie ĂŒberall ohne SpezialfĂ€lle anzeigen kann.

Auth, Berechtigungen und Sicherheit im Offline‑Modus

Baue deine Sync‑Warteschlange visuell
Modelliere eine Sync‑Warteschlange und Wiederholungen mit visueller Logik statt individuellem Glue‑Code.
AppMaster testen

Offline Ă€ndert dein Sicherheitsmodell. Ein Nutzer kann Aktionen tĂ€tigen, ohne Verbindung, aber dein Server bleibt die Quelle der Wahrheit. Behandle jede wartende Änderung als „angefordert“, nicht als „genehmigt“.

Ablauf der Anmeldung im Offline‑Zustand

Tokens laufen ab. Wenn das offline passiert, lass den Nutzer trotzdem Änderungen erstellen und speichere sie als ausstehend. TĂ€usche nicht vor, dass Aktionen, die ServerbestĂ€tigung brauchen (Zahlungen, Admin‑Genehmigungen), abgeschlossen sind. Markiere sie als ausstehend, bis ein erfolgreicher Auth‑Refresh stattgefunden hat.

Wenn die App wieder online ist, versuche zuerst ein stilles Refresh. Wenn du den Nutzer zur Anmeldung auffordern musst, mache es einmal, dann setze den Sync automatisch fort.

Nach dem Re‑Login validiere jeden wartenden Eintrag nochmal, bevor du ihn sendest. Die NutzeridentitĂ€t kann sich geĂ€ndert haben (gemeinsames GerĂ€t) und alte Änderungen dĂŒrfen nicht unter dem falschen Konto synchronisiert werden.

BerechtigungsÀnderungen und verbotene Aktionen

Berechtigungen können sich Ă€ndern, wĂ€hrend der Nutzer offline ist. Eine gestern erlaubte Änderung kann heute verboten sein. Behandle das ausdrĂŒcklich:

  • ÜberprĂŒfe serverseitig jede wartende Aktion auf Berechtigung
  • Bei Verbot stoppe den Eintrag und zeige einen klaren Grund
  • Bewahre die lokale Änderung, damit der Nutzer sie kopieren oder Zugriff anfragen kann
  • Vermeide wiederholte Versuche bei „forbidden“‑Fehlern

Beispiel: Ein Support‑Agent bearbeitet offline eine Kundennotiz im Flugzeug. Über Nacht wird seine Rolle entfernt. Beim Sync lehnt der Server das Update ab. Die App sollte anzeigen: „Kann nicht hochgeladen werden: Du hast keinen Zugriff mehr“ und die Notiz als lokalen Entwurf behalten.

Sensible Daten offline speichern

Speichere nur das Minimum, das nötig ist, um Bildschirme darzustellen und die Warteschlange abzuspielen. VerschlĂŒssele lokalen Speicher, meide das Cachen von Secrets und setze klare Regeln fĂŒr Logout (z. B. lokale Daten löschen oder EntwĂŒrfe nur mit expliziter Zustimmung behalten). Wenn du mit AppMaster arbeitest, starte mit dessen Auth‑Modul und gestalte deine Warteschlange so, dass sie immer auf eine gĂŒltige Session wartet, bevor Änderungen gesendet werden.

HĂ€ufige Fallen, die Arbeit verloren gehen oder Duplikate erzeugen lassen

Die meisten Offline‑Bugs sind nicht spektakulĂ€r. Sie entstehen aus ein paar kleinen Entscheidungen, die harmlos wirken, wenn du mit perfektem WLAN testest, aber die reale Arbeit spĂ€ter kaputtmachen.

Ein hĂ€ufiger Fehler sind stille Überschreibungen. Wenn die App eine Ă€ltere Version hochlĂ€dt und der Server sie ohne PrĂŒfung akzeptiert, kannst du eine neuere Änderung einer anderen Person löschen, und niemand bemerkt es, bis es zu spĂ€t ist. Synchronisiere mit einer Versionsnummer (oder einem updatedAt‑Zeitstempel) und weigere dich zu ĂŒberschreiben, wenn der Server weiter ist, sodass die Nutzerin eine klare Wahl bekommt.

Eine andere Falle ist ein Retry‑Sturm. Wenn ein Telefon wieder Verbindung bekommt, kann die App den Backend alle paar Sekunden zuspammen, Akku leeren und doppelte Writes erzeugen. Wiederholungen sollten ruhig sein: nach jedem Fehler langsamer werden und etwas ZufĂ€lligkeit einbauen, damit nicht tausende GerĂ€te gleichzeitig erneut versuchen.

Die Fehler, die am hĂ€ufigsten zu Datenverlust oder Duplikaten fĂŒhren:

  • Behandle jeden Fehler als „Netzwerk“: trenne permanente Fehler (ungĂŒltige Daten, fehlende Berechtigung) von temporĂ€ren (Timeout).
  • Verstecke Sync‑Fehler: wenn Leute nicht sehen, was fehlgeschlagen ist, machen sie die Aufgabe nochmal und erzeugen zwei DatensĂ€tze.
  • Sende dieselbe Änderung zweimal ohne Schutz: hĂ€nge immer eine eindeutige Request‑ID an, damit der Server Duplikate erkennt und ignoriert.
  • Textfelder automatisch mergen ohne Information: wenn du Änderungen automatisch kombinierst, lass Nutzer das Ergebnis ĂŒberprĂŒfen, wenn es wichtig ist.
  • DatensĂ€tze offline ohne stabile ID erstellen: verwende eine temporĂ€re lokale ID und mappe sie auf die Server‑ID nach dem Upload, damit spĂ€tere Änderungen nicht einen zweiten Datensatz erzeugen.

Ein schnelles Beispiel: Ein Field‑Tech erstellt offline einen neuen „Site Visit“ und bearbeitet ihn zweimal, bevor die Verbindung zurĂŒckkommt. Wenn der Create‑Call erneut versucht wird und zwei Server‑DatensĂ€tze erzeugt, hĂ€ngen spĂ€tere Änderungen möglicherweise am falschen Eintrag. Stabile IDs und serverseitiges Deduping verhindern das.

Wenn du das mit AppMaster baust, Ă€ndern sich die Regeln nicht. Der Unterschied ist nur, wo du sie implementierst: in deiner Sync‑Logik, im Datenmodell und in den Bildschirmen, die „failed“ vs „sent“ anzeigen.

Beispielszenario: zwei Personen bearbeiten denselben Datensatz

Ruhige UX fĂŒr ausstehende Änderungen gestalten
Richte ZustÀnde wie queued, syncing, failed ein, damit Nutzer immer wissen, was passiert ist.
Sync testen

Eine Field‑Technikerin, Maya, aktualisiert in einem Keller das Ticket „Job #1842“. Sie Ă€ndert den Status von „In progress“ auf „Completed“ und fĂŒgt die Notiz hinzu: „Ventil ersetzt, getestet OK.“ Die App speichert sofort und zeigt den Eintrag als ausstehend an.

Oben arbeitet ihr Kollege Leo online am selben Job. Er Àndert die geplante Zeit und weist den Auftrag einem anderen Techniker zu, weil ein Kunde ein Update gemeldet hat.

Als Maya wieder Empfang hat, startet der Hintergrund‑Sync leise. So lĂ€uft es in einem vorhersehbaren, nutzerfreundlichen Ablauf:

  1. Mayas Änderung ist noch in der Sync‑Warteschlange (Job‑ID, geĂ€nderte Felder, Zeitstempel und die Version, die sie zuletzt gesehen hat).
  2. Die App versucht hochzuladen. Der Server antwortet: „Dieser Job wurde seit deiner Version aktualisiert“ (Konflikt).
  3. Deine Konfliktregel greift: Status und Notizen können gemerged werden, aber ZuweisungsÀnderungen gewinnen, wenn sie spÀter auf dem Server gemacht wurden.
  4. Der Server akzeptiert ein gemergtes Ergebnis: status = „Completed“ (von Maya), Notiz hinzugefĂŒgt (von Maya), zugewiesener Techniker = Leos Änderung (von Leo).
  5. Der Job erscheint in Mayas App mit einem klaren Banner: „Synchronisiert mit Änderungen. Zuweisung wurde wĂ€hrend deiner Offline‑Zeit geĂ€ndert.“ Eine kleine „ÜberprĂŒfen“‑Aktion zeigt, was sich geĂ€ndert hat.

FĂŒge einen Fehler hinzu: Mayas Login‑Token lief offline ab. Der erste Sync‑Versuch schlĂ€gt fehl mit „Anmeldung erforderlich“. Die App behĂ€lt ihre Änderungen, markiert sie als „Pausiert“ und zeigt eine einfache Aufforderung. Nach der Anmeldung setzt der Sync automatisch fort, ohne dass sie etwas neu tippen muss.

Wenn es ein Validierungsproblem gibt (z. B. „Completed“ erfordert ein Foto), soll die App nicht raten. Sie markiert den Eintrag als „Benötigt Aufmerksamkeit“, sagt genau, was fehlt, und lĂ€sst ihn neu senden, wenn alles vollstĂ€ndig ist.

Plattformen wie AppMaster helfen hier, weil du Warteschlange, Konfliktregeln und Pending‑ZustĂ€nde visuell designen kannst und trotzdem echte native Kotlin‑ und SwiftUI‑Apps auslieferst.

Kurze Checkliste und nÀchste Schritte

Behandle Offline‑Sync wie ein End‑to‑End‑Feature, das du testen kannst — nicht als Ansammlung von Reparaturen. Das Ziel ist simpel: Nutzer sollen nie zweifeln, ob ihre Arbeit gespeichert ist, und die App darf keine ĂŒberraschenden Duplikate erzeugen.

Eine kurze Checkliste, um das Fundament zu prĂŒfen:

  • Die Sync‑Warteschlange liegt auf dem GerĂ€t und jede Änderung hat eine stabile lokale ID plus eine Server‑ID, wenn verfĂŒgbar.
  • Klare Status existieren (queued, syncing, sent, failed, needs review) und werden konsistent verwendet.
  • Requests sind idempotent (wiederholbar), und jede Operation enthĂ€lt einen Idempotency‑Key.
  • DatensĂ€tze haben Versionierung (updatedAt, Revisionsnummer oder ETag), damit Konflikte erkannt werden können.
  • Konfliktregeln sind in klarer Sprache formuliert (was gewinnt, was wird gemerged, wann fragt man den Nutzer).

Wenn das steht, prĂŒfe, ob das Erlebnis genauso robust ist wie das Datenmodell. Nutzer sollten sehen können, was aussteht, verstehen, was fehlgeschlagen ist, und handeln können, ohne Angst vor Datenverlust.

Teste mit realistischen Szenarien:

  • Flugmodus‑Bearbeitungen: erstellen, aktualisieren, löschen und dann reconnecten.
  • Flackerndes Netz: Verbindung mitten im Sync verlieren und sicherstellen, dass Retries keine Duplikate erzeugen.
  • App beendet: wĂ€hrend des Sendens erzwingen, dass die App geschlossen wird, wieder öffnen und prĂŒfen, ob die Warteschlange wiederhergestellt wird.
  • Uhr‑Abweichung: GerĂ€tzeit ist falsch; prĂŒfen, ob Konflikterkennung trotzdem funktioniert.
  • Doppelte Taps: Nutzer drĂŒckt Speichern zweimal; prĂŒfen, ob es zu einer Server‑Änderung wird.

Prototyp den kompletten Ablauf, bevor du die UI polierst. Baue einen Bildschirm, einen Datensatztyp und einen Konfliktfall (zwei Änderungen am selben Feld). FĂŒge einen einfachen Sync‑Statusbereich, einen Retry‑Button fĂŒr Fehler und eine klare Konfliktseite hinzu. Wenn das funktioniert, wiederhole es fĂŒr weitere Bildschirme.

Wenn du ohne Code baust, kann AppMaster (appmaster.io) native Kotlin‑ und SwiftUI‑Apps zusammen mit dem Backend generieren, sodass du dich auf Warteschlange, VersionsprĂŒfungen und nutzerseitige ZustĂ€nde konzentrieren kannst, statt alles von Hand zu verdrahten.

Einfach zu starten
Erschaffe etwas Erstaunliches

Experimentieren Sie mit AppMaster mit kostenlosem Plan.
Wenn Sie fertig sind, können Sie das richtige Abonnement auswÀhlen.

Starten
Offline‑First Hintergrund‑Synchronisation mobiler Apps: Konflikte, Wiederholungen und UX | AppMaster